FRE-600: Fix code review blockers

- Consolidated duplicate UndoManagers to single instance
- Fixed connection promise to only resolve on 'connected' status
- Fixed WebSocketProvider import (WebsocketProvider)
- Added proper doc.destroy() cleanup
- Renamed isPresenceInitialized property to avoid conflict

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-04-25 00:08:01 -04:00
parent 65b552bb08
commit 7c684a42cc
48450 changed files with 5679671 additions and 383 deletions

View File

@@ -0,0 +1,192 @@
import type { Address } from 'abitype'
import type { Client } from '../../../clients/createClient.js'
import type { Transport } from '../../../clients/transports/createTransport.js'
import type { Account } from '../../../types/account.js'
import type { WalletGrantPermissionsReturnType } from '../../../types/eip1193.js'
import type { Hex } from '../../../types/misc.js'
import type { OneOf } from '../../../types/utils.js'
import { numberToHex, parseAccount } from '../../../utils/index.js'
import type { Permission } from '../types/permission.js'
import type { Signer } from '../types/signer.js'
export type GrantPermissionsParameters = {
/** Timestamp (in seconds) that specifies the time by which this session MUST expire. */
expiry: number
/** Set of permissions to grant to the user. */
permissions: readonly Permission[]
} & OneOf<
| {
/** Signer to assign the permissions to. */
signer?: Signer | undefined
}
| {
/** Account to assign the permissions to. */
account?: Address | Account | undefined
}
>
export type GrantPermissionsReturnType = {
/** Timestamp (in seconds) that specifies the time by which this session MUST expire. */
expiry: number
/** ERC-4337 Factory to deploy smart contract account. */
factory?: Hex | undefined
/** Calldata to use when calling the ERC-4337 Factory. */
factoryData?: string | undefined
/** Set of granted permissions. */
grantedPermissions: readonly Permission[]
/** Permissions identifier. */
permissionsContext: string
/** Signer attached to the permissions. */
signerData?:
| {
userOpBuilder?: Hex | undefined
submitToAddress?: Hex | undefined
}
| undefined
}
/**
* Request permissions from a wallet to perform actions on behalf of a user.
*
* - Docs: https://viem.sh/experimental/erc7715/grantPermissions
*
* @example
* import { createWalletClient, custom } from 'viem'
* import { mainnet } from 'viem/chains'
* import { grantPermissions } from 'viem/experimental'
*
* const client = createWalletClient({
* chain: mainnet,
* transport: custom(window.ethereum),
* })
*
* const result = await grantPermissions(client, {
* expiry: 1716846083638,
* permissions: [
* {
* type: 'native-token-transfer',
* data: {
* ticker: 'ETH',
* },
* policies: [
* {
* type: 'token-allowance',
* data: {
* allowance: parseEther('1'),
* },
* }
* ],
* required: true,
* },
* ],
* })
*/
export async function grantPermissions(
client: Client<Transport>,
parameters: GrantPermissionsParameters,
): Promise<GrantPermissionsReturnType> {
const { account, expiry, permissions, signer } = parameters
const result = await client.request(
{
method: 'wallet_grantPermissions',
params: [
formatParameters({ account, expiry, permissions, signer } as any),
],
},
{ retryCount: 0 },
)
return formatRequest(result) as GrantPermissionsReturnType
}
function formatParameters(parameters: GrantPermissionsParameters) {
const { expiry, permissions, signer: signer_ } = parameters
const account = parameters.account
? parseAccount(parameters.account)
: undefined
const signer = (() => {
if (!account && !signer_) return undefined
// JSON-RPC Account as signer.
if (account?.type === 'json-rpc')
return {
type: 'wallet',
}
// Local Account as signer.
if (account?.type === 'local')
return {
type: 'account',
data: {
id: account.address,
},
}
// ERC-7715 Signer as signer.
return signer_
})()
return {
expiry,
permissions: permissions.map((permission) => ({
...permission,
policies: permission.policies.map((policy) => {
const data = (() => {
if (policy.type === 'token-allowance')
return {
allowance: numberToHex(policy.data.allowance),
}
if (policy.type === 'gas-limit')
return {
limit: numberToHex(policy.data.limit),
}
return policy.data
})()
return {
data,
type:
typeof policy.type === 'string' ? policy.type : policy.type.custom,
}
}),
required: permission.required ?? false,
type:
typeof permission.type === 'string'
? permission.type
: permission.type.custom,
})),
...(signer ? { signer } : {}),
}
}
function formatRequest(result: WalletGrantPermissionsReturnType) {
return {
expiry: result.expiry,
...(result.factory ? { factory: result.factory } : {}),
...(result.factoryData ? { factoryData: result.factoryData } : {}),
grantedPermissions: result.grantedPermissions.map((permission) => ({
...permission,
policies: permission.policies.map((policy) => {
const data = (() => {
if (policy.type === 'token-allowance')
return {
allowance: BigInt((policy.data as any).allowance),
}
if (policy.type === 'gas-limit')
return {
limit: BigInt((policy.data as any).limit),
}
return policy.data
})()
return {
data,
type: policy.type,
}
}),
})),
permissionsContext: result.permissionsContext,
...(result.signerData ? { signerData: result.signerData } : {}),
}
}

View File

@@ -0,0 +1,80 @@
import type { Client } from '../../../clients/createClient.js'
import type { Transport } from '../../../clients/transports/createTransport.js'
import type { Account } from '../../../types/account.js'
import type { Chain } from '../../../types/chain.js'
import {
type GrantPermissionsParameters,
type GrantPermissionsReturnType,
grantPermissions,
} from '../actions/grantPermissions.js'
export type Erc7715Actions = {
/**
* Request permissions from a wallet to perform actions on behalf of a user.
*
* - Docs: https://viem.sh/experimental/erc7715/grantPermissions
*
* @example
* import { createWalletClient, custom } from 'viem'
* import { mainnet } from 'viem/chains'
* import { erc7715Actions } from 'viem/experimental'
*
* const client = createWalletClient({
* chain: mainnet,
* transport: custom(window.ethereum),
* }).extend(erc7715Actions())
*
* const result = await client.grantPermissions({
* expiry: 1716846083638,
* permissions: [
* {
* type: 'contract-call',
* data: {
* address: '0x0000000000000000000000000000000000000000',
* },
* },
* {
* type: 'native-token-limit',
* data: {
* amount: 69420n,
* },
* required: true,
* },
* ],
* })
*/
grantPermissions: (
parameters: GrantPermissionsParameters,
) => Promise<GrantPermissionsReturnType>
}
/**
* A suite of ERC-7715 Wallet Actions.
*
* - Docs: https://viem.sh/experimental
*
* @example
* import { createPublicClient, createWalletClient, http } from 'viem'
* import { mainnet } from 'viem/chains'
* import { erc7715Actions } from 'viem/experimental'
*
* const walletClient = createWalletClient({
* chain: mainnet,
* transport: http(),
* }).extend(erc7715Actions())
*
* const result = await walletClient.grantPermissions({...})
*/
export function erc7715Actions() {
return <
transport extends Transport,
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
>(
client: Client<transport, chain, account>,
): Erc7715Actions => {
return {
grantPermissions: (parameters) => grantPermissions(client, parameters),
}
}
}

View File

@@ -0,0 +1,53 @@
import type { Address } from 'abitype'
import type { OneOf } from '../../../types/utils.js'
import type { Policy } from './policy.js'
/** @internal */
export type CustomPermission<data = unknown, type = { custom: string }> = {
data: data
type: type
}
/** @internal */
export type NativeTokenTransferPermission = {
type: 'native-token-transfer'
data: {
/** Native token ticker (e.g. ETH). */
ticker: string
}
}
/** @internal */
export type Erc20TokenTransferPermission = {
type: 'erc20-token-transfer'
data: {
/** ERC20 address. */
address: Address
/** Native token ticker (e.g. ETH). */
ticker: string
}
}
/** @internal */
export type ContractCallPermission = {
type: 'contract-call'
data: {
/** Contract address. */
address: Address
/** Set of contract signatures to permit. */
calls: string[]
}
}
export type Permission<uint256 = bigint> = OneOf<
| NativeTokenTransferPermission
| Erc20TokenTransferPermission
| ContractCallPermission
| CustomPermission
> & {
/** Set of policies for the permission. */
policies: readonly Policy<uint256>[]
/** Whether or not the wallet must grant the permission. */
required?: boolean | undefined
}

43
node_modules/viem/experimental/erc7715/types/policy.ts generated vendored Normal file
View File

@@ -0,0 +1,43 @@
import type { OneOf } from '../../../types/utils.js'
/** @internal */
export type CustomPolicy<data = unknown> = {
data: data
type: { custom: string }
}
/** @internal */
export type TokenAllowancePolicy<uint256 = bigint> = {
type: 'token-allowance'
data: {
/** Token allowance (in wei). */
allowance: uint256
}
}
/** @internal */
export type GasLimitPolicy<uint256 = bigint> = {
type: 'gas-limit'
data: {
/** Gas limit (in wei). */
limit: uint256
}
}
/** @internal */
export type RateLimitPolicy = {
type: 'rate-limit'
data: {
/** Number of times during each interval. */
count: number
/** Interval (in seconds). */
interval: number
}
}
export type Policy<amount = bigint> = OneOf<
| TokenAllowancePolicy<amount>
| GasLimitPolicy<amount>
| RateLimitPolicy
| CustomPolicy
>

35
node_modules/viem/experimental/erc7715/types/signer.ts generated vendored Normal file
View File

@@ -0,0 +1,35 @@
import type { Address } from 'abitype'
import type { OneOf } from '../../../types/utils.js'
/** @internal */
export type AccountSigner = {
type: 'account'
data: {
id: Address
}
}
/** @internal */
export type KeySigner = {
type: 'key'
data: {
id: string
}
}
/** @internal */
export type MultiKeySigner = {
type: 'keys'
data: {
ids: string[]
}
}
/** @internal */
export type WalletSigner = {
type: 'wallet'
}
export type Signer = OneOf<
AccountSigner | KeySigner | MultiKeySigner | WalletSigner
>