diff --git a/.eslintignore b/.eslintignore index 53bb867ee8..bdeea5f1cf 100644 --- a/.eslintignore +++ b/.eslintignore @@ -6,6 +6,7 @@ site/.vitepress/cache/**/* /examples/* !/examples/ui-demo +/examples/ui-demo/contracts /examples/ui-demo/.next/* **/.turbo/* diff --git a/.gitmodules b/.gitmodules index 336230713d..e66ab99492 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,9 @@ [submodule "examples/embedded-accounts-quickstart"] path = examples/embedded-accounts-quickstart url = https://github.com/alchemyplatform/embedded-accounts-quickstart +[submodule "examples/ui-demo/contracts/lib/openzeppelin-contracts"] + path = examples/ui-demo/contracts/lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts +[submodule "examples/ui-demo/contracts/lib/forge-std"] + path = examples/ui-demo/contracts/lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/.vitest/package.json b/.vitest/package.json index fe39e5a084..89da57cf3b 100644 --- a/.vitest/package.json +++ b/.vitest/package.json @@ -9,7 +9,7 @@ "prool": "^0.0.15", "tar": "^7.4.1", "typescript-template": "*", - "viem": "2.20.0" + "viem": "2.22.6" }, "dependencies": { "@aa-sdk/core": "^4.0.0-alpha.8" diff --git a/aa-sdk/core/package.json b/aa-sdk/core/package.json index f2e45bcf4d..7561f51ce5 100644 --- a/aa-sdk/core/package.json +++ b/aa-sdk/core/package.json @@ -54,7 +54,7 @@ "zod": "^3.22.4" }, "peerDependencies": { - "viem": "^2.20.0" + "viem": "^2.22.6" }, "repository": { "type": "git", diff --git a/aa-sdk/core/src/account/smartContractAccount.ts b/aa-sdk/core/src/account/smartContractAccount.ts index ed2f790d59..0f72442103 100644 --- a/aa-sdk/core/src/account/smartContractAccount.ts +++ b/aa-sdk/core/src/account/smartContractAccount.ts @@ -154,7 +154,10 @@ export type ToSmartContractAccountParams< // if not provided, will default to just using signMessage over the Hex signUserOperationHash?: (uoHash: Hex) => Promise; encodeUpgradeToAndCall?: (params: UpgradeToAndCallParams) => Promise; -} & Omit; +} & Omit< + CustomSource, + "signTransaction" | "address" | "experimental_signAuthorization" +>; // [!endregion ToSmartContractAccountParams] /** diff --git a/aa-sdk/core/src/actions/smartAccount/internal/sendUserOperation.ts b/aa-sdk/core/src/actions/smartAccount/internal/sendUserOperation.ts index e89aeaecc5..ddf5302cb4 100644 --- a/aa-sdk/core/src/actions/smartAccount/internal/sendUserOperation.ts +++ b/aa-sdk/core/src/actions/smartAccount/internal/sendUserOperation.ts @@ -50,6 +50,17 @@ export async function _sendUserOperation< overrides, }); + // TODO: check if this is the place to add the auth tuple, if not, remove + // if ( + // request.signature.startsWith( + // // TODO: put this in a constant + // "0x00000000000000000000000000000000000000000000000001ff00" + // ) && + // account.signAuthorization + // ) { + // request.authorizationTuple = await account.signAuthorization(); + // } + return { hash: await client.sendRawUserOperation(request, entryPoint.address), request, diff --git a/aa-sdk/core/src/client/decorators/bundlerClient.ts b/aa-sdk/core/src/client/decorators/bundlerClient.ts index 94a48446f6..e188b89f44 100644 --- a/aa-sdk/core/src/client/decorators/bundlerClient.ts +++ b/aa-sdk/core/src/client/decorators/bundlerClient.ts @@ -63,7 +63,10 @@ export type BundlerActions = { estimateUserOperationGas< TEntryPointVersion extends EntryPointVersion = EntryPointVersion >( - request: UserOperationRequest, + request: Extract< + UserOperationRequest, + { authorizationContract?: Address } + >, entryPoint: Address, stateOverride?: StateOverride ): Promise>; diff --git a/aa-sdk/core/src/entrypoint/0.7.ts b/aa-sdk/core/src/entrypoint/0.7.ts index 678b4cb5a5..327c80e479 100644 --- a/aa-sdk/core/src/entrypoint/0.7.ts +++ b/aa-sdk/core/src/entrypoint/0.7.ts @@ -65,7 +65,7 @@ const packUserOperation = (request: UserOperationRequest<"0.7.0">): Hex => { { type: "bytes32" }, ], [ - request.sender as Address, + request.sender, hexToBigInt(request.nonce), keccak256(initCode), keccak256(request.callData), diff --git a/aa-sdk/core/src/index.ts b/aa-sdk/core/src/index.ts index 5f66aae5cc..aa41ebb334 100644 --- a/aa-sdk/core/src/index.ts +++ b/aa-sdk/core/src/index.ts @@ -92,6 +92,8 @@ export { } from "./errors/useroperation.js"; export { LogLevel, Logger } from "./logger.js"; export { middlewareActions } from "./middleware/actions.js"; +export { default7702UserOpSigner } from "./middleware/defaults/7702signer.js"; +export { default7702GasEstimator } from "./middleware/defaults/7702gasEstimator.js"; export { defaultFeeEstimator } from "./middleware/defaults/feeEstimator.js"; export { defaultGasEstimator } from "./middleware/defaults/gasEstimator.js"; export { defaultPaymasterAndData } from "./middleware/defaults/paymasterAndData.js"; diff --git a/aa-sdk/core/src/middleware/defaults/7702gasEstimator.ts b/aa-sdk/core/src/middleware/defaults/7702gasEstimator.ts new file mode 100644 index 0000000000..2f546df377 --- /dev/null +++ b/aa-sdk/core/src/middleware/defaults/7702gasEstimator.ts @@ -0,0 +1,44 @@ +import { AccountNotFoundError } from "../../errors/account.js"; +import type { UserOperationStruct } from "../../types.js"; +import type { ClientMiddlewareFn } from "../types"; +import { defaultGasEstimator } from "./gasEstimator.js"; + +/** + * A middleware function to estimate the gas usage of a user operation with an optional custom gas estimator. + * This function is only compatible with accounts using EntryPoint v0.7.0. + * + * @param {ClientMiddlewareFn} [gasEstimator] An optional custom gas estimator function + * @returns {Function} A function that takes user operation structure and parameters, estimates gas usage, and returns the estimated user operation + */ +export const default7702GasEstimator: ( + gasEstimator?: ClientMiddlewareFn +) => ClientMiddlewareFn = + (gasEstimator?: ClientMiddlewareFn) => async (struct, params) => { + const gasEstimator_ = gasEstimator ?? defaultGasEstimator(params.client); + + const account = params.account ?? params.client.account; + if (!account) { + throw new AccountNotFoundError(); + } + + const entryPoint = account.getEntryPoint(); + if (entryPoint.version !== "0.7.0") { + throw new Error( + "This middleware is only compatible with EntryPoint v0.7.0" + ); + } + + // todo: this is currently overloading the meaning of the getImplementationAddress method, replace with a dedicated method or clarify intention in docs + const implementationAddress = await account.getImplementationAddress(); + + // todo: do we need to omit this from estimation if the account is already 7702 delegated? Not omitting for now. + + (struct as UserOperationStruct<"0.7.0">).authorizationContract = + implementationAddress; + + const estimatedUO = await gasEstimator_(struct, params); + + estimatedUO.authorizationContract = undefined; // Strip out authorizationContract after estimation. + + return estimatedUO; + }; diff --git a/aa-sdk/core/src/middleware/defaults/7702signer.ts b/aa-sdk/core/src/middleware/defaults/7702signer.ts new file mode 100644 index 0000000000..58d7c3fe11 --- /dev/null +++ b/aa-sdk/core/src/middleware/defaults/7702signer.ts @@ -0,0 +1,79 @@ +import { toHex } from "viem"; +import { isSmartAccountWithSigner } from "../../account/smartContractAccount.js"; +import { AccountNotFoundError } from "../../errors/account.js"; +import { ChainNotFoundError } from "../../errors/client.js"; +import type { ClientMiddlewareFn } from "../types"; +import { defaultUserOpSigner } from "./userOpSigner.js"; + +/** + * Provides a default middleware function for signing user operations with a client account when using ERC-7702 to upgrade local accounts to smart accounts. + * If the SmartAccount doesn't support `signAuthorization`, then this just runs the provided `signUserOperation` middleware + * + * @param {ClientMiddlewareFn} [userOpSigner] Optional user operation signer function + * @returns {Function} An async function that processes the user operation and returns the authorized operation with an authorization tuple if necessary + */ +export const default7702UserOpSigner: ( + userOpSigner?: ClientMiddlewareFn +) => ClientMiddlewareFn = + (userOpSigner?: ClientMiddlewareFn) => async (struct, params) => { + const userOpSigner_ = userOpSigner ?? defaultUserOpSigner; + + const uo = await userOpSigner_(struct, params); + + const account = params.account ?? params.client.account; + const { client } = params; + + if (!account || !isSmartAccountWithSigner(account)) { + throw new AccountNotFoundError(); + } + + const signer = account.getSigner(); + + if (!signer.signAuthorization) { + console.log("account does not support signAuthorization"); + return uo; + } + + if (!client.chain) { + throw new ChainNotFoundError(); + } + + const code = (await client.getCode({ address: account.address })) ?? "0x"; + // TODO: this isn't the cleanest because now the account implementation HAS to know that it needs to return an impl address + // even if the account is not deployed + + const implAddress = await account.getImplementationAddress(); + + const expectedCode = "0xef0100" + implAddress.slice(2); + + if (code.toLowerCase() === expectedCode.toLowerCase()) { + return uo; + } + + const accountNonce = await params.client.getTransactionCount({ + address: account.address, + }); + + const { + r, + s, + v, + yParity = v ? v - 27n : undefined, + } = await signer.signAuthorization({ + chainId: client.chain.id, + contractAddress: implAddress, + nonce: accountNonce, + }); + + return { + ...uo, + authorizationTuple: { + chainId: client.chain.id, + nonce: toHex(accountNonce), // deepHexlify doesn't encode number(0) correctly, it returns "0x" + address: implAddress, + r, + s, + yParity: Number(yParity), + }, + }; + }; diff --git a/aa-sdk/core/src/signer/local-account.ts b/aa-sdk/core/src/signer/local-account.ts index 46b5f0bc0d..328001133d 100644 --- a/aa-sdk/core/src/signer/local-account.ts +++ b/aa-sdk/core/src/signer/local-account.ts @@ -14,6 +14,7 @@ import { privateKeyToAccount, } from "viem/accounts"; import type { SmartAccountSigner } from "./types.js"; +import type { Authorization } from "viem/experimental"; /** * Represents a local account signer and provides methods to sign messages and transactions, as well as static methods to create the signer from mnemonic or private key. @@ -95,6 +96,33 @@ export class LocalAccountSigner< return this.inner.signTypedData(params); }; + /** + * Signs an unsigned authorization using the provided private key account. + * + * @example + * ```ts + * import { LocalAccountSigner } from "@aa-sdk/core"; + * import { generatePrivateKey } from "viem"; + * + * const signer = LocalAccountSigner.mnemonicToAccountSigner(generatePrivateKey()); + * const signedAuthorization = await signer.signAuthorization({ + * contractAddress: "0x1234123412341234123412341234123412341234", + * chainId: 1, + * nonce: 3, + * }); + * ``` + * + * @param {Authorization} unsignedAuthorization - The unsigned authorization to be signed. + * @returns {Promise>} A promise that resolves to the signed authorization. + */ + + signAuthorization( + this: LocalAccountSigner, + unsignedAuthorization: Authorization + ): Promise> { + return this.inner.experimental_signAuthorization(unsignedAuthorization); + } + /** * Returns the address of the inner object in a specific hexadecimal format. * diff --git a/aa-sdk/core/src/signer/types.ts b/aa-sdk/core/src/signer/types.ts index 369da4d098..6c530feea4 100644 --- a/aa-sdk/core/src/signer/types.ts +++ b/aa-sdk/core/src/signer/types.ts @@ -5,6 +5,7 @@ import type { TypedData, TypedDataDefinition, } from "viem"; +import type { Authorization } from "viem/experimental"; // [!region SmartAccountAuthenticator] /** @@ -42,5 +43,9 @@ export interface SmartAccountSigner { >( params: TypedDataDefinition ) => Promise; + + signAuthorization?: ( + unsignedAuthorization: Authorization + ) => Promise>; } // [!endregion SmartAccountSigner] diff --git a/aa-sdk/core/src/types.ts b/aa-sdk/core/src/types.ts index bbe276f2e4..91259a5130 100644 --- a/aa-sdk/core/src/types.ts +++ b/aa-sdk/core/src/types.ts @@ -5,6 +5,7 @@ import { type StateOverride, type TransactionReceipt, } from "viem"; +import type { Authorization } from "viem/experimental"; import type { z } from "zod"; import type { UserOperationFeeOptionsFieldSchema, @@ -201,15 +202,20 @@ export interface UserOperationRequest_v7 { } // [!endregion UserOperationRequest_v7] +export type Eip7702ExtendedFields = + | { authorizationTuple?: Authorization; authorizationContract?: never } + | { authorizationTuple?: never; authorizationContract?: Address }; + // [!region UserOperationRequest] // Reference: https://eips.ethereum.org/EIPS/eip-4337#definitions export type UserOperationRequest< TEntryPointVersion extends EntryPointVersion = EntryPointVersion -> = TEntryPointVersion extends "0.6.0" +> = (TEntryPointVersion extends "0.6.0" ? UserOperationRequest_v6 : TEntryPointVersion extends "0.7.0" ? UserOperationRequest_v7 - : never; + : never) & + Eip7702ExtendedFields; // [!endregion UserOperationRequest] @@ -347,9 +353,10 @@ export interface UserOperationStruct_v7 { // [!region UserOperationStruct] export type UserOperationStruct< TEntryPointVersion extends EntryPointVersion = EntryPointVersion -> = TEntryPointVersion extends "0.6.0" +> = (TEntryPointVersion extends "0.6.0" ? UserOperationStruct_v6 : TEntryPointVersion extends "0.7.0" ? UserOperationStruct_v7 - : never; + : never) & + Eip7702ExtendedFields; // [!endregion UserOperationStruct] diff --git a/aa-sdk/ethers/package.json b/aa-sdk/ethers/package.json index 8f85340d36..436d9deffb 100644 --- a/aa-sdk/ethers/package.json +++ b/aa-sdk/ethers/package.json @@ -60,7 +60,7 @@ "@ethersproject/wallet": "^5.7.0" }, "peerDependencies": { - "viem": "^2.20.0" + "viem": "^2.22.6" }, "repository": { "type": "git", diff --git a/account-kit/core/package.json b/account-kit/core/package.json index 8b8393ded9..5ddb2c9df8 100644 --- a/account-kit/core/package.json +++ b/account-kit/core/package.json @@ -54,7 +54,7 @@ "zustand": "^5.0.0-rc.2" }, "peerDependencies": { - "viem": "^2.20.0", + "viem": "^2.22.6", "wagmi": "^2.12.7" }, "publishConfig": { diff --git a/account-kit/infra/package.json b/account-kit/infra/package.json index 2912b185b3..72b8939d10 100644 --- a/account-kit/infra/package.json +++ b/account-kit/infra/package.json @@ -50,7 +50,7 @@ "zod": "^3.22.4" }, "peerDependencies": { - "viem": "^2.20.0" + "viem": "^2.22.6" }, "publishConfig": { "access": "public", diff --git a/account-kit/plugingen/package.json b/account-kit/plugingen/package.json index ee59eda39a..8eab22cdde 100644 --- a/account-kit/plugingen/package.json +++ b/account-kit/plugingen/package.json @@ -76,6 +76,6 @@ "zod": "^3.22.4" }, "peerDependencies": { - "viem": "^2.20.0" + "viem": "^2.22.6" } } diff --git a/account-kit/react/package.json b/account-kit/react/package.json index f4c449b689..0ce5a55dd3 100644 --- a/account-kit/react/package.json +++ b/account-kit/react/package.json @@ -84,11 +84,11 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "tailwindcss": "^3.4.3", - "viem": "^2.20.0", + "viem": "^2.22.6", "wagmi": "^2.12.7" }, "resolutions": { - "viem": "2.20.0" + "viem": "2.22.6" }, "publishConfig": { "access": "public", diff --git a/account-kit/signer/package.json b/account-kit/signer/package.json index 911cadd005..489471c830 100644 --- a/account-kit/signer/package.json +++ b/account-kit/signer/package.json @@ -58,7 +58,7 @@ "zod": "^3.22.4" }, "peerDependencies": { - "viem": "^2.20.0" + "viem": "^2.22.6" }, "publishConfig": { "access": "public", diff --git a/account-kit/signer/src/base.ts b/account-kit/signer/src/base.ts index 352f85145b..371f4e3792 100644 --- a/account-kit/signer/src/base.ts +++ b/account-kit/signer/src/base.ts @@ -36,6 +36,7 @@ import { } from "./types.js"; import { assertNever } from "./utils/typeAssertions.js"; import type { SessionManagerEvents } from "./session/types"; +import { hashAuthorization, type Authorization } from "viem/experimental"; export interface BaseAlchemySignerParams { client: TClient; @@ -51,6 +52,12 @@ type AlchemySignerStore = { isNewUser?: boolean; }; +type UnpackedSignature = { + r: `0x${string}`; + s: `0x${string}`; + v: bigint; +}; + type InternalStore = Mutate< StoreApi, [["zustand/subscribeWithSelector", never]] @@ -524,16 +531,64 @@ export abstract class BaseAlchemySigner keccak256(serializedTx) ); - const signature = { - r: takeBytes(signatureHex, { count: 32 }), - s: takeBytes(signatureHex, { count: 32, offset: 32 }), - v: BigInt(takeBytes(signatureHex, { count: 1, offset: 64 })), - }; + const signature = this.unpackSignRawMessageBytes(signatureHex); return serializeFn(tx, signature); } ); + /** + * Signs an EIP-7702 Authorization and then returns the authorization with the signature. + * + * @example + * ```ts + * import { AlchemyWebSigner } from "@account-kit/signer"; + * + * const signer = new AlchemyWebSigner({ + * client: { + * connection: { + * rpcUrl: "/api/rpc", + * }, + * iframeConfig: { + * iframeContainerId: "alchemy-signer-iframe-container", + * }, + * }, + * }); + * + * const tx = await signer.signAuthorization({ + * contractAddress: "0x1234", + * chainId: 1, + * nonce: 0, + * }); + * ``` + * + * @param {Authorization} unsignedAuthorization the authorization to be signed + * @returns {Promise> | undefined} a promise that resolves to the authorization with the signature + */ + signAuthorization: ( + unsignedAuthorization: Authorization + ) => Promise> = SignerLogger.profiled( + "BaseAlchemySigner.signAuthorization", + async (unsignedAuthorization) => { + const hashedAuthorization = hashAuthorization(unsignedAuthorization); + const signedAuthorizationHex = await this.inner.signRawMessage( + hashedAuthorization + ); + const signature = this.unpackSignRawMessageBytes(signedAuthorizationHex); + return { ...unsignedAuthorization, ...signature }; + } + ); + + private unpackSignRawMessageBytes = ( + hex: `0x${string}` + ): UnpackedSignature => { + return { + r: takeBytes(hex, { count: 32 }), + s: takeBytes(hex, { count: 32, offset: 32 }), + v: BigInt(takeBytes(hex, { count: 1, offset: 64 })), + }; + }; + /** * Unauthenticated call to look up a user's organizationId by email * diff --git a/account-kit/smart-contracts/package.json b/account-kit/smart-contracts/package.json index 2f5127ff58..1e1845ccb0 100644 --- a/account-kit/smart-contracts/package.json +++ b/account-kit/smart-contracts/package.json @@ -77,6 +77,6 @@ "@account-kit/infra": "^4.8.0" }, "peerDependencies": { - "viem": "^2.20.0" + "viem": "^2.22.6" } } diff --git a/account-kit/smart-contracts/src/ma-v2/account/common/modularAccountV2Base.ts b/account-kit/smart-contracts/src/ma-v2/account/common/modularAccountV2Base.ts new file mode 100644 index 0000000000..af487ef102 --- /dev/null +++ b/account-kit/smart-contracts/src/ma-v2/account/common/modularAccountV2Base.ts @@ -0,0 +1,217 @@ +import { + createBundlerClient, + getEntryPoint, + InvalidEntityIdError, + InvalidNonceKeyError, + type AccountOp, + type EntryPointDef, + type SmartAccountSigner, + type SmartContractAccountWithSigner, + type ToSmartContractAccountParams, +} from "@aa-sdk/core"; +import { DEFAULT_OWNER_ENTITY_ID } from "../../utils.js"; +import { + type Hex, + type Address, + type Chain, + type Transport, + encodeFunctionData, + maxUint32, + zeroAddress, + getContract, + concatHex, + maxUint152, +} from "viem"; +import { modularAccountAbi } from "../../abis/modularAccountAbi.js"; +import { serializeModuleEntity } from "../../actions/common/utils.js"; + +export const executeUserOpSelector: Hex = "0x8DD7712F"; + +export type SignerEntity = { + isGlobalValidation: boolean; + entityId: number; +}; + +export type ExecutionDataView = { + module: Address; + skipRuntimeValidation: boolean; + allowGlobalValidation: boolean; + executionHooks: readonly Hex[]; +}; + +export type ValidationDataView = { + validationHooks: readonly Hex[]; + executionHooks: readonly Hex[]; + selectors: readonly Hex[]; + validationFlags: number; +}; + +export type ValidationDataParams = + | { + validationModuleAddress: Address; + entityId?: never; + } + | { + validationModuleAddress?: never; + entityId: number; + }; + +export type MAV2Account< + TSigner extends SmartAccountSigner = SmartAccountSigner +> = SmartContractAccountWithSigner<"MAV2Account", TSigner, "0.7.0"> & { + signerEntity: SignerEntity; + getExecutionData: (selector: Hex) => Promise; + getValidationData: ( + args: ValidationDataParams + ) => Promise; + encodeCallData: (callData: Hex) => Promise; +}; + +export type CreateMAV2BaseFunctionsParams< + TTransport extends Transport = Transport +> = Pick< + ToSmartContractAccountParams<"MAV2Account", TTransport, Chain, "0.7.0">, + "transport" | "chain" +> & { + // salt?: bigint; + // factoryAddress?: Address; + // initCode?: Hex; + // initialOwner?: Address; + entryPoint?: EntryPointDef<"0.7.0", Chain>; + signerEntity?: SignerEntity; + accountAddress: Address; +}; + +export async function createMAv2BaseFunctions( + config: CreateMAV2BaseFunctionsParams +) { + const { + transport, + chain, + entryPoint = getEntryPoint(chain, { version: "0.7.0" }), + signerEntity: { + isGlobalValidation = true, + entityId = DEFAULT_OWNER_ENTITY_ID, + } = {}, + accountAddress, + } = config; + + if (entityId > Number(maxUint32)) { + throw new InvalidEntityIdError(entityId); + } + + const client = createBundlerClient({ + transport, + chain, + }); + + const encodeExecute: (tx: AccountOp) => Promise = async ({ + target, + data, + value, + }) => + await encodeCallData( + encodeFunctionData({ + abi: modularAccountAbi, + functionName: "execute", + args: [target, value ?? 0n, data], + }) + ); + + const encodeBatchExecute: (txs: AccountOp[]) => Promise = async (txs) => + await encodeCallData( + encodeFunctionData({ + abi: modularAccountAbi, + functionName: "executeBatch", + args: [ + txs.map((tx) => ({ + target: tx.target, + data: tx.data, + value: tx.value ?? 0n, + })), + ], + }) + ); + + const isAccountDeployed: () => Promise = async () => + !!(await client.getCode({ address: accountAddress })); + // TODO: add deferred action flag + const getAccountNonce = async (nonceKey: bigint = 0n): Promise => { + if (nonceKey > maxUint152) { + throw new InvalidNonceKeyError(nonceKey); + } + + const entryPointContract = getContract({ + address: entryPoint.address, + abi: entryPoint.abi, + client, + }); + + const fullNonceKey: bigint = + (nonceKey << 40n) + + BigInt(entityId << 8) + + (isGlobalValidation ? 1n : 0n); + + return entryPointContract.read.getNonce([ + accountAddress, + fullNonceKey, + ]) as Promise; + }; + + const accountContract = getContract({ + address: accountAddress, + abi: modularAccountAbi, + client, + }); + + const getExecutionData = async (selector: Hex) => { + if (!(await isAccountDeployed())) { + return { + module: zeroAddress, + skipRuntimeValidation: false, + allowGlobalValidation: false, + executionHooks: [], + }; + } + + return await accountContract.read.getExecutionData([selector]); + }; + + const getValidationData = async (args: ValidationDataParams) => { + if (!(await isAccountDeployed())) { + return { + validationHooks: [], + executionHooks: [], + selectors: [], + validationFlags: 0, + }; + } + + const { validationModuleAddress, entityId } = args; + return await accountContract.read.getValidationData([ + serializeModuleEntity({ + moduleAddress: validationModuleAddress ?? zeroAddress, + entityId: entityId ?? Number(maxUint32), + }), + ]); + }; + + const encodeCallData = async (callData: Hex): Promise => { + const validationData = await getValidationData({ + entityId: Number(entityId), + }); + + return validationData.executionHooks.length + ? concatHex([executeUserOpSelector, callData]) + : callData; + }; + + return { + getExecutionData, + getValidationData, + encodeCallData, + getAccountNonce, + encodeExecute, + encodeBatchExecute, + }; +} diff --git a/account-kit/smart-contracts/src/ma-v2/account/semiModularAccount7702.ts b/account-kit/smart-contracts/src/ma-v2/account/semiModularAccount7702.ts new file mode 100644 index 0000000000..383776d916 --- /dev/null +++ b/account-kit/smart-contracts/src/ma-v2/account/semiModularAccount7702.ts @@ -0,0 +1,113 @@ +import type { + EntryPointDef, + SmartAccountSigner, + ToSmartContractAccountParams, +} from "@aa-sdk/core"; +import { + getEntryPoint, + toSmartContractAccount, + EntityIdOverrideError, +} from "@aa-sdk/core"; +import { type Chain, type Hex, type Transport, type Address } from "viem"; +import { DEFAULT_OWNER_ENTITY_ID } from "../utils.js"; +import { singleSignerMessageSigner } from "../modules/single-signer-validation/signer.js"; +import { nativeSMASigner } from "./nativeSMASigner.js"; +import { + type SignerEntity, + type MAV2Account, + createMAv2BaseFunctions, +} from "./common/modularAccountV2Base.js"; + +export type CreateSMA7702AccountParams< + TTransport extends Transport = Transport, + TSigner extends SmartAccountSigner = SmartAccountSigner +> = Pick< + ToSmartContractAccountParams<"MAV2Account", TTransport, Chain, "0.7.0">, + "transport" | "chain" | "accountAddress" +> & { + signer: TSigner; + entryPoint?: EntryPointDef<"0.7.0", Chain>; + signerEntity?: SignerEntity; +}; + +export async function createSMA7702Account< + TTransport extends Transport = Transport, + TSigner extends SmartAccountSigner = SmartAccountSigner +>( + config: CreateSMA7702AccountParams +): Promise>; + +/** + * Creates an SMAV2 account using defined parameters including chain, signer, salt, factory address, and more. + * Handles account initialization code, nonce generation, transaction encoding, and more to construct a modular account with optional validation hooks. + * + * @param {CreateSMA7702ccountParams} config Configuration parameters for creating an SMAV2 account. Includes chain details, signer, salt, factory address, and more. + * @returns {Promise} A promise that resolves to an `MAV2Account` providing methods for nonce retrieval, transaction execution, and more. + */ +export async function createSMA7702Account( + config: CreateSMA7702AccountParams +): Promise { + const { + transport, + chain, + signer, + accountAddress, + entryPoint = getEntryPoint(chain, { version: "0.7.0" }), + signerEntity = { + isGlobalValidation: true, + entityId: DEFAULT_OWNER_ENTITY_ID, + }, + signerEntity: { entityId = DEFAULT_OWNER_ENTITY_ID } = {}, + } = config; + + const getAccountInitCode = async (): Promise => { + return "0x"; + }; + + const signerAddress = await signer.getAddress(); + + // Account address is either loaded from the parameter, or inferred as the signer address (due to 7702) + const _accountAddress = accountAddress ?? signerAddress; + + if ( + entityId === DEFAULT_OWNER_ENTITY_ID && + signerAddress !== _accountAddress + ) { + throw new EntityIdOverrideError(); + } + + const { encodeExecute, encodeBatchExecute, ...baseFunctions } = + await createMAv2BaseFunctions({ + transport, + chain, + entryPoint, + signerEntity, + accountAddress: _accountAddress, + }); + + const baseAccount = await toSmartContractAccount({ + transport, + chain, + entryPoint, + accountAddress: _accountAddress, + source: `MAV2Account`, + encodeExecute, + encodeBatchExecute, + getAccountInitCode, + ...(entityId === DEFAULT_OWNER_ENTITY_ID + ? nativeSMASigner(signer, chain, _accountAddress) + : singleSignerMessageSigner(signer, chain, _accountAddress, entityId)), + }); + + const implementation: Address = "0x69007702764179f14F51cdce752f4f775d74E139"; + + const getImplementationAddress = async () => implementation; + + return { + ...baseAccount, + ...baseFunctions, + getSigner: () => signer, + signerEntity, + getImplementationAddress, + }; +} diff --git a/account-kit/smart-contracts/src/ma-v2/account/semiModularAccountV2.ts b/account-kit/smart-contracts/src/ma-v2/account/semiModularAccountV2.ts index 83bf5d5772..c0f6d44b32 100644 --- a/account-kit/smart-contracts/src/ma-v2/account/semiModularAccountV2.ts +++ b/account-kit/smart-contracts/src/ma-v2/account/semiModularAccountV2.ts @@ -1,25 +1,17 @@ import type { EntryPointDef, SmartAccountSigner, - AccountOp, - SmartContractAccountWithSigner, ToSmartContractAccountParams, } from "@aa-sdk/core"; import { createBundlerClient, getEntryPoint, toSmartContractAccount, - InvalidEntityIdError, - InvalidNonceKeyError, getAccountAddress, } from "@aa-sdk/core"; import { concatHex, encodeFunctionData, - getContract, - maxUint32, - maxUint152, - zeroAddress, type Address, type Chain, type Hex, @@ -32,50 +24,11 @@ import { } from "../utils.js"; import { singleSignerMessageSigner } from "../modules/single-signer-validation/signer.js"; import { nativeSMASigner } from "./nativeSMASigner.js"; -import { modularAccountAbi } from "../abis/modularAccountAbi.js"; -import { serializeModuleEntity } from "../actions/common/utils.js"; - -const executeUserOpSelector: Hex = "0x8DD7712F"; - -export type SignerEntity = { - isGlobalValidation: boolean; - entityId: number; -}; - -export type ExecutionDataView = { - module: Address; - skipRuntimeValidation: boolean; - allowGlobalValidation: boolean; - executionHooks: readonly Hex[]; -}; - -export type ValidationDataView = { - validationHooks: readonly Hex[]; - executionHooks: readonly Hex[]; - selectors: readonly Hex[]; - validationFlags: number; -}; - -export type ValidationDataParams = - | { - validationModuleAddress: Address; - entityId?: never; - } - | { - validationModuleAddress?: never; - entityId: number; - }; - -export type MAV2Account< - TSigner extends SmartAccountSigner = SmartAccountSigner -> = SmartContractAccountWithSigner<"MAV2Account", TSigner, "0.7.0"> & { - signerEntity: SignerEntity; - getExecutionData: (selector: Hex) => Promise; - getValidationData: ( - args: ValidationDataParams - ) => Promise; - encodeCallData: (callData: Hex) => Promise; -}; +import { + type SignerEntity, + type MAV2Account, + createMAv2BaseFunctions, +} from "./common/modularAccountV2Base.js"; export type CreateSMAV2AccountParams< TTransport extends Transport = Transport, @@ -124,16 +77,9 @@ export async function createSMAV2Account( isGlobalValidation: true, entityId: DEFAULT_OWNER_ENTITY_ID, }, - signerEntity: { - isGlobalValidation = true, - entityId = DEFAULT_OWNER_ENTITY_ID, - } = {}, + signerEntity: { entityId = DEFAULT_OWNER_ENTITY_ID } = {}, } = config; - if (entityId > Number(maxUint32)) { - throw new InvalidEntityIdError(entityId); - } - const client = createBundlerClient({ transport, chain, @@ -157,34 +103,6 @@ export async function createSMAV2Account( ]); }; - const encodeExecute: (tx: AccountOp) => Promise = async ({ - target, - data, - value, - }) => - await encodeCallData( - encodeFunctionData({ - abi: modularAccountAbi, - functionName: "execute", - args: [target, value ?? 0n, data], - }) - ); - - const encodeBatchExecute: (txs: AccountOp[]) => Promise = async (txs) => - await encodeCallData( - encodeFunctionData({ - abi: modularAccountAbi, - functionName: "executeBatch", - args: [ - txs.map((tx) => ({ - target: tx.target, - data: tx.data, - value: tx.value ?? 0n, - })), - ], - }) - ); - const _accountAddress = await getAccountAddress({ client, entryPoint, @@ -192,6 +110,15 @@ export async function createSMAV2Account( getAccountInitCode, }); + const { encodeExecute, encodeBatchExecute, ...baseFunctions } = + await createMAv2BaseFunctions({ + transport, + chain, + entryPoint, + signerEntity, + accountAddress: _accountAddress, + }); + const baseAccount = await toSmartContractAccount({ transport, chain, @@ -206,84 +133,10 @@ export async function createSMAV2Account( : singleSignerMessageSigner(signer, chain, _accountAddress, entityId)), }); - // TODO: add deferred action flag - const getAccountNonce = async (nonceKey: bigint = 0n): Promise => { - if (nonceKey > maxUint152) { - throw new InvalidNonceKeyError(nonceKey); - } - - const entryPointContract = getContract({ - address: entryPoint.address, - abi: entryPoint.abi, - client, - }); - - const fullNonceKey: bigint = - (nonceKey << 40n) + - BigInt(entityId << 8) + - (isGlobalValidation ? 1n : 0n); - - return entryPointContract.read.getNonce([ - _accountAddress, - fullNonceKey, - ]) as Promise; - }; - - const accountContract = getContract({ - address: _accountAddress, - abi: modularAccountAbi, - client, - }); - - const getExecutionData = async (selector: Hex) => { - if (!(await baseAccount.isAccountDeployed())) { - return { - module: zeroAddress, - skipRuntimeValidation: false, - allowGlobalValidation: false, - executionHooks: [], - }; - } - - return await accountContract.read.getExecutionData([selector]); - }; - - const getValidationData = async (args: ValidationDataParams) => { - if (!(await baseAccount.isAccountDeployed())) { - return { - validationHooks: [], - executionHooks: [], - selectors: [], - validationFlags: 0, - }; - } - - const { validationModuleAddress, entityId } = args; - return await accountContract.read.getValidationData([ - serializeModuleEntity({ - moduleAddress: validationModuleAddress ?? zeroAddress, - entityId: entityId ?? Number(maxUint32), - }), - ]); - }; - - const encodeCallData = async (callData: Hex): Promise => { - const validationData = await getValidationData({ - entityId: Number(entityId), - }); - - return validationData.executionHooks.length - ? concatHex([executeUserOpSelector, callData]) - : callData; - }; - return { ...baseAccount, - getAccountNonce, + ...baseFunctions, getSigner: () => signer, signerEntity, - getExecutionData, - getValidationData, - encodeCallData, }; } diff --git a/account-kit/smart-contracts/src/ma-v2/actions/install-validation/installValidation.ts b/account-kit/smart-contracts/src/ma-v2/actions/install-validation/installValidation.ts index ffc1c38fea..0cfaf5db3b 100644 --- a/account-kit/smart-contracts/src/ma-v2/actions/install-validation/installValidation.ts +++ b/account-kit/smart-contracts/src/ma-v2/actions/install-validation/installValidation.ts @@ -24,8 +24,8 @@ import { serializeModuleEntity, } from "../common/utils.js"; -import { type SMAV2AccountClient } from "../../client/client.js"; -import { type MAV2Account } from "../../account/semiModularAccountV2.js"; +import { type SMAV2AccountClient } from "../../client/smabv2.js"; +import { type MAV2Account } from "../../account/common/modularAccountV2Base.js"; import { DEFAULT_OWNER_ENTITY_ID } from "../../utils.js"; export type InstallValidationParams< diff --git a/account-kit/smart-contracts/src/ma-v2/client/sma7702.ts b/account-kit/smart-contracts/src/ma-v2/client/sma7702.ts new file mode 100644 index 0000000000..7ff4264de4 --- /dev/null +++ b/account-kit/smart-contracts/src/ma-v2/client/sma7702.ts @@ -0,0 +1,79 @@ +import { + createSmartAccountClient, + type SmartAccountClient, + type SmartAccountSigner, + type SmartAccountClientConfig, +} from "@aa-sdk/core"; +import { type Chain, type Transport } from "viem"; + +import { + createSMA7702Account, + type CreateSMA7702AccountParams, +} from "../account/semiModularAccount7702.js"; + +import { default7702UserOpSigner, default7702GasEstimator } from "@aa-sdk/core"; + +import type { MAV2Account } from "../account/common/modularAccountV2Base.js"; + +export type SMA7702AccountClient< + TSigner extends SmartAccountSigner = SmartAccountSigner +> = SmartAccountClient>; + +export type CreateSMA7702AccountClientParams< + TTransport extends Transport = Transport, + TChain extends Chain = Chain, + TSigner extends SmartAccountSigner = SmartAccountSigner +> = CreateSMA7702AccountParams & + Omit< + SmartAccountClientConfig, + "transport" | "account" | "chain" + >; + +export function createSMA7702AccountClient< + TChain extends Chain = Chain, + TSigner extends SmartAccountSigner = SmartAccountSigner +>( + args: CreateSMA7702AccountClientParams +): Promise>; + +/** + * Creates a SMAv2 account client using the provided configuration parameters. + * + * @example + * ```ts + * import { http } from "viem"; + * import { createSMAV2AccountClient } from "@account-kit/smart-contracts"; + * import { LocalAccountSigner } from "@aa-sdk/core"; + * import { sepolia } from "@account-kit/infra"; + * + * const MNEMONIC = "..."; + * const RPC_URL = "..."; + * + * const signer = LocalAccountSigner.mnemonicToAccountSigner(MNEMONIC); + * + * const chain = sepolia; + * + * const transport = http(RPC_URL); + * + * const SMAV2SignerAccountClient = await createSMAV2AccountClient({ + * chain, + * signer, + * transport, + * }); + * ``` + * + * @param {CreateSMAV2AccountClientParams} config The configuration parameters required to create the MAv2 account client + * @returns {Promise} A promise that resolves to a `SmartAccountClient` instance + */ +export async function createSMA7702AccountClient( + config: CreateSMA7702AccountClientParams +): Promise { + const sma7702Account = await createSMA7702Account(config); + + return createSmartAccountClient({ + account: sma7702Account, + gasEstimator: default7702GasEstimator(config.gasEstimator), + signUserOperation: default7702UserOpSigner(config.signUserOperation), + ...config, + }); +} diff --git a/account-kit/smart-contracts/src/ma-v2/client/client.ts b/account-kit/smart-contracts/src/ma-v2/client/smabv2.ts similarity index 96% rename from account-kit/smart-contracts/src/ma-v2/client/client.ts rename to account-kit/smart-contracts/src/ma-v2/client/smabv2.ts index 58bf4f3dc6..fc6cdf9a42 100644 --- a/account-kit/smart-contracts/src/ma-v2/client/client.ts +++ b/account-kit/smart-contracts/src/ma-v2/client/smabv2.ts @@ -9,9 +9,10 @@ import { type Chain, type Transport } from "viem"; import { createSMAV2Account, type CreateSMAV2AccountParams, - type MAV2Account, } from "../account/semiModularAccountV2.js"; +import type { MAV2Account } from "../account/common/modularAccountV2Base.js"; + export type SMAV2AccountClient< TSigner extends SmartAccountSigner = SmartAccountSigner > = SmartAccountClient>; diff --git a/account-kit/smart-contracts/src/ma-v2/index.ts b/account-kit/smart-contracts/src/ma-v2/index.ts index 11ff8382bc..da1a31e535 100644 --- a/account-kit/smart-contracts/src/ma-v2/index.ts +++ b/account-kit/smart-contracts/src/ma-v2/index.ts @@ -7,6 +7,7 @@ export { semiModularAccountStorageAbi } from "./abis/semiModularAccountStorageAb export { nativeSMASigner } from "./account/nativeSMASigner.js"; export type * from "./account/semiModularAccountV2.js"; export { createSMAV2Account } from "./account/semiModularAccountV2.js"; +export { createSMA7702Account } from "./account/semiModularAccount7702.js"; export type { ModuleEntity, @@ -23,8 +24,10 @@ export { export type * from "./actions/install-validation/installValidation.js"; export { installValidationActions } from "./actions/install-validation/installValidation.js"; -export type * from "./client/client.js"; -export { createSMAV2AccountClient } from "./client/client.js"; +export type * from "./client/smabv2.js"; +export type * from "./client/sma7702.js"; +export { createSMAV2AccountClient } from "./client/smabv2.js"; +export { createSMA7702AccountClient } from "./client/sma7702.js"; export { getDefaultAllowlistModuleAddress, diff --git a/examples/ui-demo/contracts/.gitignore b/examples/ui-demo/contracts/.gitignore new file mode 100644 index 0000000000..920b50ddf0 --- /dev/null +++ b/examples/ui-demo/contracts/.gitignore @@ -0,0 +1,23 @@ +# Foundry build and cache directories +out/ +out-optimized/ +cache/ +node_modules/ + +# Coverage +report/ +lcov.info + +# env vars +.env + +# deployments +broadcast/**/run-latest.json +broadcast/**/dry-run/**/* + +# misc +.DS_Store +**/.DS_Store + +# Monorepo support: unhide lib/ +!lib/ \ No newline at end of file diff --git a/examples/ui-demo/contracts/Deployments.md b/examples/ui-demo/contracts/Deployments.md new file mode 100644 index 0000000000..c0d6b9a12c --- /dev/null +++ b/examples/ui-demo/contracts/Deployments.md @@ -0,0 +1,11 @@ +## Mock Swap Venue + +Salt: 0 + +Swap: 0xB0AEC4c25E8332256A91bBaf169E3C32dfC3C33C +DemoUSDC: 0xCFf7C6dA719408113DFcb5e36182c6d5aa491443 +DemoWETH: 0x0766798566D1f6e2f0b126f7783aaB2CBb81c66f + +## AccountKit Demo NFT + +0x7E06a337929B1Cb92363e15414e37959a36E5338 \ No newline at end of file diff --git a/examples/ui-demo/contracts/README.md b/examples/ui-demo/contracts/README.md new file mode 100644 index 0000000000..9265b45584 --- /dev/null +++ b/examples/ui-demo/contracts/README.md @@ -0,0 +1,66 @@ +## Foundry + +**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** + +Foundry consists of: + +- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). +- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. +- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. +- **Chisel**: Fast, utilitarian, and verbose solidity REPL. + +## Documentation + +https://book.getfoundry.sh/ + +## Usage + +### Build + +```shell +$ forge build +``` + +### Test + +```shell +$ forge test +``` + +### Format + +```shell +$ forge fmt +``` + +### Gas Snapshots + +```shell +$ forge snapshot +``` + +### Anvil + +```shell +$ anvil +``` + +### Deploy + +```shell +$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key +``` + +### Cast + +```shell +$ cast +``` + +### Help + +```shell +$ forge --help +$ anvil --help +$ cast --help +``` diff --git a/examples/ui-demo/contracts/broadcast/DeployNFT.s.sol/911867/run-1736807829.json b/examples/ui-demo/contracts/broadcast/DeployNFT.s.sol/911867/run-1736807829.json new file mode 100644 index 0000000000..60b056b486 --- /dev/null +++ b/examples/ui-demo/contracts/broadcast/DeployNFT.s.sol/911867/run-1736807829.json @@ -0,0 +1,57 @@ +{ + "transactions": [ + { + "hash": "0x02ae4a484c89989ca992c8024646256c2e37a21bb1d9aab9235fd9a4ae0b92d6", + "transactionType": "CREATE2", + "contractName": "NFT", + "contractAddress": "0x7e06a337929b1cb92363e15414e37959a36e5338", + "function": null, + "arguments": [ + "Account Kit Demo NFT", + "AKD", + "https://static.alchemyapi.io/assets/accountkit/accountkit.jpg" + ], + "transaction": { + "from": "0xddf32240b4ca3184de7ec8f0d5aba27dec8b7a5c", + "to": "0x4e59b44847b379578588920ca78fbf26c0b4956c", + "gas": "0x15dc14", + "value": "0x0", + "input": "0x0000000000000000000000000000000000000000000000000000000000000000608060405234801561000f575f80fd5b5060405161124b38038061124b83398101604081905261002e916100ff565b82825f61003b8382610212565b5060016100488282610212565b506006915061005990508282610212565b505050506102cc565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112610085575f80fd5b81516001600160401b0381111561009e5761009e610062565b604051601f8201601f19908116603f011681016001600160401b03811182821017156100cc576100cc610062565b6040528181528382016020018510156100e3575f80fd5b8160208501602083015e5f918101602001919091529392505050565b5f805f60608486031215610111575f80fd5b83516001600160401b03811115610126575f80fd5b61013286828701610076565b602086015190945090506001600160401b0381111561014f575f80fd5b61015b86828701610076565b604086015190935090506001600160401b03811115610178575f80fd5b61018486828701610076565b9150509250925092565b600181811c908216806101a257607f821691505b6020821081036101c057634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561020d57805f5260205f20601f840160051c810160208510156101eb5750805b601f840160051c820191505b8181101561020a575f81556001016101f7565b50505b505050565b81516001600160401b0381111561022b5761022b610062565b61023f81610239845461018e565b846101c6565b6020601f821160018114610271575f831561025a5750848201515b5f19600385901b1c1916600184901b17845561020a565b5f84815260208120601f198516915b828110156102a05787850151825560209485019460019092019101610280565b50848210156102bd57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b610f72806102d95f395ff3fe6080604052600436106100ee575f3560e01c80636c0360eb11610087578063a22cb46511610057578063a22cb46514610279578063b88d4fde14610298578063c87b56dd146102b7578063e985e9c5146102d6575f80fd5b80636c0360eb1461021f57806370a0823114610233578063755edd171461025257806395d89b4114610265575f80fd5b8063095ea7b3116100c2578063095ea7b3146101a157806323b872dd146101c257806342842e0e146101e15780636352211e14610200575f80fd5b80629a9b7b146100f257806301ffc9a71461011a57806306fdde0314610149578063081812fc1461016a575b5f80fd5b3480156100fd575f80fd5b5061010760075481565b6040519081526020015b60405180910390f35b348015610125575f80fd5b50610139610134366004610c48565b6102f5565b6040519015158152602001610111565b348015610154575f80fd5b5061015d610346565b6040516101119190610c98565b348015610175575f80fd5b50610189610184366004610caa565b6103d5565b6040516001600160a01b039091168152602001610111565b3480156101ac575f80fd5b506101c06101bb366004610cdc565b6103fc565b005b3480156101cd575f80fd5b506101c06101dc366004610d04565b61040b565b3480156101ec575f80fd5b506101c06101fb366004610d04565b610499565b34801561020b575f80fd5b5061018961021a366004610caa565b6104b8565b34801561022a575f80fd5b5061015d6104c2565b34801561023e575f80fd5b5061010761024d366004610d3e565b61054e565b610107610260366004610d3e565b610593565b348015610270575f80fd5b5061015d6105b4565b348015610284575f80fd5b506101c0610293366004610d57565b6105c3565b3480156102a3575f80fd5b506101c06102b2366004610da4565b6105ce565b3480156102c2575f80fd5b5061015d6102d1366004610caa565b6105e6565b3480156102e1575f80fd5b506101396102f0366004610e81565b6106a9565b5f6001600160e01b031982166380ac58cd60e01b148061032557506001600160e01b03198216635b5e139f60e01b145b8061034057506301ffc9a760e01b6001600160e01b03198316145b92915050565b60605f805461035490610eb2565b80601f016020809104026020016040519081016040528092919081815260200182805461038090610eb2565b80156103cb5780601f106103a2576101008083540402835291602001916103cb565b820191905f5260205f20905b8154815290600101906020018083116103ae57829003601f168201915b5050505050905090565b5f6103df826106d6565b505f828152600460205260409020546001600160a01b0316610340565b61040782823361070e565b5050565b6001600160a01b03821661043957604051633250574960e11b81525f60048201526024015b60405180910390fd5b5f61044583833361071b565b9050836001600160a01b0316816001600160a01b031614610493576040516364283d7b60e01b81526001600160a01b0380861660048301526024820184905282166044820152606401610430565b50505050565b6104b383838360405180602001604052805f8152506105ce565b505050565b5f610340826106d6565b600680546104cf90610eb2565b80601f01602080910402602001604051908101604052809291908181526020018280546104fb90610eb2565b80156105465780601f1061051d57610100808354040283529160200191610546565b820191905f5260205f20905b81548152906001019060200180831161052957829003601f168201915b505050505081565b5f6001600160a01b038216610578576040516322718ad960e21b81525f6004820152602401610430565b506001600160a01b03165f9081526003602052604090205490565b5f8060075f81546105a390610eea565b91829055509050610340838261080d565b60606001805461035490610eb2565b610407338383610826565b6105d984848461040b565b61049333858585856108c4565b60605f6105f2836104b8565b6001600160a01b0316036106195760405163d872946b60e01b815260040160405180910390fd5b6006805461062690610eb2565b80601f016020809104026020016040519081016040528092919081815260200182805461065290610eb2565b801561069d5780601f106106745761010080835404028352916020019161069d565b820191905f5260205f20905b81548152906001019060200180831161068057829003601f168201915b50505050509050919050565b6001600160a01b039182165f90815260056020908152604080832093909416825291909152205460ff1690565b5f818152600260205260408120546001600160a01b03168061034057604051637e27328960e01b815260048101849052602401610430565b6104b383838360016109ec565b5f828152600260205260408120546001600160a01b039081169083161561074757610747818486610af0565b6001600160a01b03811615610781576107625f855f806109ec565b6001600160a01b0381165f90815260036020526040902080545f190190555b6001600160a01b038516156107af576001600160a01b0385165f908152600360205260409020805460010190555b5f8481526002602052604080822080546001600160a01b0319166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b610407828260405180602001604052805f815250610b54565b6001600160a01b03821661085857604051630b61174360e31b81526001600160a01b0383166004820152602401610430565b6001600160a01b038381165f81815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b156109e557604051630a85bd0160e11b81526001600160a01b0384169063150b7a0290610906908890889087908790600401610f0e565b6020604051808303815f875af1925050508015610940575060408051601f3d908101601f1916820190925261093d91810190610f4a565b60015b6109a7573d80801561096d576040519150601f19603f3d011682016040523d82523d5f602084013e610972565b606091505b5080515f0361099f57604051633250574960e11b81526001600160a01b0385166004820152602401610430565b805181602001fd5b6001600160e01b03198116630a85bd0160e11b146109e357604051633250574960e11b81526001600160a01b0385166004820152602401610430565b505b5050505050565b8080610a0057506001600160a01b03821615155b15610ac1575f610a0f846106d6565b90506001600160a01b03831615801590610a3b5750826001600160a01b0316816001600160a01b031614155b8015610a4e5750610a4c81846106a9565b155b15610a775760405163a9fbf51f60e01b81526001600160a01b0384166004820152602401610430565b8115610abf5783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50505f90815260046020526040902080546001600160a01b0319166001600160a01b0392909216919091179055565b610afb838383610b6b565b6104b3576001600160a01b038316610b2957604051637e27328960e01b815260048101829052602401610430565b60405163177e802f60e01b81526001600160a01b038316600482015260248101829052604401610430565b610b5e8383610bcf565b6104b3335f8585856108c4565b5f6001600160a01b03831615801590610bc75750826001600160a01b0316846001600160a01b03161480610ba45750610ba484846106a9565b80610bc757505f828152600460205260409020546001600160a01b038481169116145b949350505050565b6001600160a01b038216610bf857604051633250574960e11b81525f6004820152602401610430565b5f610c0483835f61071b565b90506001600160a01b038116156104b3576040516339e3563760e11b81525f6004820152602401610430565b6001600160e01b031981168114610c45575f80fd5b50565b5f60208284031215610c58575f80fd5b8135610c6381610c30565b9392505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610c636020830184610c6a565b5f60208284031215610cba575f80fd5b5035919050565b80356001600160a01b0381168114610cd7575f80fd5b919050565b5f8060408385031215610ced575f80fd5b610cf683610cc1565b946020939093013593505050565b5f805f60608486031215610d16575f80fd5b610d1f84610cc1565b9250610d2d60208501610cc1565b929592945050506040919091013590565b5f60208284031215610d4e575f80fd5b610c6382610cc1565b5f8060408385031215610d68575f80fd5b610d7183610cc1565b915060208301358015158114610d85575f80fd5b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b5f805f8060808587031215610db7575f80fd5b610dc085610cc1565b9350610dce60208601610cc1565b925060408501359150606085013567ffffffffffffffff811115610df0575f80fd5b8501601f81018713610e00575f80fd5b803567ffffffffffffffff811115610e1a57610e1a610d90565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610e4957610e49610d90565b604052818152828201602001891015610e60575f80fd5b816020840160208301375f6020838301015280935050505092959194509250565b5f8060408385031215610e92575f80fd5b610e9b83610cc1565b9150610ea960208401610cc1565b90509250929050565b600181811c90821680610ec657607f821691505b602082108103610ee457634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60018201610f0757634e487b7160e01b5f52601160045260245ffd5b5060010190565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f90610f4090830184610c6a565b9695505050505050565b5f60208284031215610f5a575f80fd5b8151610c6381610c3056fea164736f6c634300081a000a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000144163636f756e74204b69742044656d6f204e46540000000000000000000000000000000000000000000000000000000000000000000000000000000000000003414b440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003d68747470733a2f2f7374617469632e616c6368656d796170692e696f2f6173736574732f6163636f756e746b69742f6163636f756e746b69742e6a7067000000", + "nonce": "0x24", + "chainId": "0xde9fb" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x107eb8", + "logs": [], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x02ae4a484c89989ca992c8024646256c2e37a21bb1d9aab9235fd9a4ae0b92d6", + "transactionIndex": "0x1", + "blockHash": "0x9e4144012ac3be4cda0949deacd9f4e7ec834e7aa7f1b6353e72ae36054aeff4", + "blockNumber": "0x7d5534", + "gasUsed": "0xfd376", + "effectiveGasPrice": "0xfd", + "from": "0xddf32240b4ca3184de7ec8f0d5aba27dec8b7a5c", + "to": "0x4e59b44847b379578588920ca78fbf26c0b4956c", + "contractAddress": "0x7e06a337929b1cb92363e15414e37959a36e5338", + "l1BaseFeeScalar": "0xa6fe0", + "l1BlobBaseFee": "0x337", + "l1BlobBaseFeeScalar": "0x0", + "l1Fee": "0x27ae655b4d4", + "l1GasPrice": "0x5366709", + "l1GasUsed": "0xb213" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1736807829, + "chain": 911867, + "commit": "42e6bae6" +} \ No newline at end of file diff --git a/examples/ui-demo/contracts/broadcast/DeploySwapVenue.s.sol/911867/run-1736537366.json b/examples/ui-demo/contracts/broadcast/DeploySwapVenue.s.sol/911867/run-1736537366.json new file mode 100644 index 0000000000..815725bde8 --- /dev/null +++ b/examples/ui-demo/contracts/broadcast/DeploySwapVenue.s.sol/911867/run-1736537366.json @@ -0,0 +1,97 @@ +{ + "transactions": [ + { + "hash": "0xff3fd4a479bc16ce127103e5b292c041e10b7fbb9791b5a1420016d04c89ec23", + "transactionType": "CREATE2", + "contractName": "Swap", + "contractAddress": "0xb0aec4c25e8332256a91bbaf169e3c32dfc3c33c", + "function": null, + "arguments": null, + "transaction": { + "from": "0xddf32240b4ca3184de7ec8f0d5aba27dec8b7a5c", + "to": "0x4e59b44847b379578588920ca78fbf26c0b4956c", + "gas": "0x25334e", + "value": "0x0", + "input": "0x00000000000000000000000000000000000000000000000000000000000000006080806040523461020c57610c80818101906001600160401b0382118383101761021057610882928184823960c0815f9460408152600860408201526744656d6f5553444360c01b60608201526080602082015260046080820152635553444360e01b60a08201520301905ff08015610201575f80546001600160a01b0319166001600160a01b03929092169182179055803b1561020c576040516340c10f1960e01b81523060048201526001600160a01b036024820152905f908290604490829084905af18015610201576101ec575b50604051818101939091906001600160401b038511838610176101d857839460c09284928339604081526008604082015267088cadadeae8aa8960c31b60608201526080602082015260046080820152630ae8aa8960e31b60a082015203019082f080156101cb57600180546001600160a01b0319166001600160a01b03929092169182179055803b156101c8576040516340c10f1960e01b81523060048201526001600160a01b03602482015291908290604490829084905af180156101bd576101a5575b60405161063a90816102488239f35b6101b0828092610224565b6101ba5780610196565b80fd5b6040513d84823e3d90fd5b50fd5b50604051903d90823e3d90fd5b634e487b7160e01b84526041600452602484fd5b6101f99192505f90610224565b5f905f6100d0565b6040513d5f823e3d90fd5b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b601f909101601f19168101906001600160401b038211908210176102105760405256fe6080806040526004361015610012575f80fd5b5f905f3560e01c9081631b2ef1ca14610454575080633e413bee146104035780633fc8cef3146103b1578063ccdc7d761461022d5763eebba33314610055575f80fd5b3461022a5761006336610573565b90678ac7230489e8000082116101cc5782546040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481019290925283929060209083906064908290879073ffffffffffffffffffffffffffffffffffffffff165af19081156101c15760209261015d926101a6575b5073ffffffffffffffffffffffffffffffffffffffff60015416906040519485809481937fa9059cbb00000000000000000000000000000000000000000000000000000000835233600484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b03925af1801561019b5761016f575080f35b6101909060203d602011610194575b61018881836105a7565b810190610615565b5080f35b503d61017e565b6040513d84823e3d90fd5b6101bc90843d86116101945761018881836105a7565b6100e9565b6040513d85823e3d90fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4d617820313020657468207377617020617420612074696d65000000000000006044820152fd5b80fd5b503461022a5761023c36610573565b9069152d02c7e14af68000008211610353576001546040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481019290925283929060209083906064908290879073ffffffffffffffffffffffffffffffffffffffff165af19081156101c15760209261015d92610338575b5073ffffffffffffffffffffffffffffffffffffffff845416906040519485809481937fa9059cbb00000000000000000000000000000000000000000000000000000000835233600484016020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b61034e90843d86116101945761018881836105a7565b6102c5565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4d6178203130306b2055534443207377617020617420612074696d65000000006044820152fd5b503461022a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b503461022a57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5773ffffffffffffffffffffffffffffffffffffffff6020915416604051908152f35b823461056f5761046336610573565b929073ffffffffffffffffffffffffffffffffffffffff5f541690813b1561056f577f40c10f1900000000000000000000000000000000000000000000000000000000835233600484015260248301525f908290604490829084905af1801561056457610551575b50809173ffffffffffffffffffffffffffffffffffffffff60015416803b1561054d576040517f40c10f19000000000000000000000000000000000000000000000000000000008152336004820152602481019290925282908290604490829084905af1801561019b5761053c5750f35b81610546916105a7565b61022a5780f35b5050fd5b61055d91505f906105a7565b5f826104cb565b6040513d5f823e3d90fd5b5f80fd5b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc604091011261056f576004359060243590565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176105e857604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b9081602091031261056f5751801515810361056f579056fea164736f6c634300081a000a60806040523461031057610c808038038061001981610314565b9283398101906040818303126103105780516001600160401b0381116103105782610045918301610339565b60208201519092906001600160401b038111610310576100659201610339565b81516001600160401b03811161022357600354600181811c91168015610306575b602082101461020557601f81116102a3575b50602092601f821160011461024257928192935f92610237575b50508160011b915f199060031b1c1916176003555b80516001600160401b03811161022357600454600181811c91168015610219575b602082101461020557601f81116101a2575b50602091601f8211600114610142579181925f92610137575b50508160011b915f199060031b1c1916176004555b6040516108f5908161038b8239f35b015190505f80610113565b601f1982169260045f52805f20915f5b85811061018a57508360019510610172575b505050811b01600455610128565b01515f1960f88460031b161c191690555f8080610164565b91926020600181928685015181550194019201610152565b60045f527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f830160051c810191602084106101fb575b601f0160051c01905b8181106101f057506100fa565b5f81556001016101e3565b90915081906101da565b634e487b7160e01b5f52602260045260245ffd5b90607f16906100e8565b634e487b7160e01b5f52604160045260245ffd5b015190505f806100b2565b601f1982169360035f52805f20915f5b86811061028b5750836001959610610273575b505050811b016003556100c7565b01515f1960f88460031b161c191690555f8080610265565b91926020600181928685015181550194019201610252565b60035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f830160051c810191602084106102fc575b601f0160051c01905b8181106102f15750610098565b5f81556001016102e4565b90915081906102db565b90607f1690610086565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761022357604052565b81601f82011215610310578051906001600160401b03821161022357610368601f8301601f1916602001610314565b928284526020838301011161031057815f9260208093018386015e830101529056fe6080806040526004361015610012575f80fd5b5f3560e01c90816306fdde03146106ab57508063095ea7b31461061c57806318160ddd146105ff57806323b872dd14610489578063313ce5671461046e57806340c10f19146102ec57806370a08231146102a857806395d89b411461012d578063a9059cbb146100fc5763dd62ed3e1461008a575f80fd5b346100f85760406003193601126100f8576100a36107ac565b73ffffffffffffffffffffffffffffffffffffffff6100c06107cf565b91165f52600160205273ffffffffffffffffffffffffffffffffffffffff60405f2091165f52602052602060405f2054604051908152f35b5f80fd5b346100f85760406003193601126100f8576101226101186107ac565b60243590336107f2565b602060405160018152f35b346100f8575f6003193601126100f8576040515f600454908160011c6001831692831561029e575b60208210841461027157818552849390811561022f57506001146101d3575b5003601f01601f191681019067ffffffffffffffff8211818310176101a6576101a282918260405282610782565b0390f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60045f90815291507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8183106102135750508101602001601f19610174565b60209193508060019154838588010152019101909183926101fd565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660208581019190915291151560051b84019091019150601f199050610174565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b90607f1690610155565b346100f85760206003193601126100f85773ffffffffffffffffffffffffffffffffffffffff6102d66107ac565b165f525f602052602060405f2054604051908152f35b346100f85760406003193601126100f8576103056107ac565b6024359073ffffffffffffffffffffffffffffffffffffffff82116103ea5773ffffffffffffffffffffffffffffffffffffffff169081156103be57600254908082018092116103915760207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef915f9360025584845283825260408420818154019055604051908152a3005b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7fec442f05000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4572726f723a206d6178206d696e7420616d6f756e742069732075696e74313660448201527f30206d61780000000000000000000000000000000000000000000000000000006064820152fd5b346100f8575f6003193601126100f857602060405160128152f35b346100f85760606003193601126100f8576104a26107ac565b6104aa6107cf565b6044359073ffffffffffffffffffffffffffffffffffffffff831692835f52600160205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260405f20547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110610526575b5061012293506107f2565b8381106105cb57841561059f57331561057357610122945f52600160205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f526020528360405f20910390558461051b565b7f94280d62000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b7fe602df05000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b83907ffb8f41b2000000000000000000000000000000000000000000000000000000005f523360045260245260445260645ffd5b346100f8575f6003193601126100f8576020600254604051908152f35b346100f85760406003193601126100f8576106356107ac565b60243590331561059f5773ffffffffffffffffffffffffffffffffffffffff1690811561057357335f52600160205260405f20825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b346100f8575f6003193601126100f8575f600354908160011c60018316928315610778575b60208210841461027157818552849390811561022f575060011461071c575003601f01601f191681019067ffffffffffffffff8211818310176101a6576101a282918260405282610782565b60035f90815291507fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b81831061075c5750508101602001601f19610174565b6020919350806001915483858801015201910190918392610746565b90607f16906106d0565b601f19601f602060409481855280519182918282880152018686015e5f8582860101520116010190565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036100f857565b6024359073ffffffffffffffffffffffffffffffffffffffff821682036100f857565b73ffffffffffffffffffffffffffffffffffffffff169081156108bc5773ffffffffffffffffffffffffffffffffffffffff169182156103be57815f525f60205260405f205481811061088a57817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b827fe450d38c000000000000000000000000000000000000000000000000000000005f5260045260245260445260645ffd5b7f96c6fd1e000000000000000000000000000000000000000000000000000000005f525f60045260245ffdfea164736f6c634300081a000a", + "nonce": "0x1f", + "chainId": "0xde9fb" + }, + "additionalContracts": [ + { + "transactionType": "CREATE", + "address": "0xcff7c6da719408113dfcb5e36182c6d5aa491443", + "initCode": "0x60806040523461031057610c808038038061001981610314565b9283398101906040818303126103105780516001600160401b0381116103105782610045918301610339565b60208201519092906001600160401b038111610310576100659201610339565b81516001600160401b03811161022357600354600181811c91168015610306575b602082101461020557601f81116102a3575b50602092601f821160011461024257928192935f92610237575b50508160011b915f199060031b1c1916176003555b80516001600160401b03811161022357600454600181811c91168015610219575b602082101461020557601f81116101a2575b50602091601f8211600114610142579181925f92610137575b50508160011b915f199060031b1c1916176004555b6040516108f5908161038b8239f35b015190505f80610113565b601f1982169260045f52805f20915f5b85811061018a57508360019510610172575b505050811b01600455610128565b01515f1960f88460031b161c191690555f8080610164565b91926020600181928685015181550194019201610152565b60045f527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f830160051c810191602084106101fb575b601f0160051c01905b8181106101f057506100fa565b5f81556001016101e3565b90915081906101da565b634e487b7160e01b5f52602260045260245ffd5b90607f16906100e8565b634e487b7160e01b5f52604160045260245ffd5b015190505f806100b2565b601f1982169360035f52805f20915f5b86811061028b5750836001959610610273575b505050811b016003556100c7565b01515f1960f88460031b161c191690555f8080610265565b91926020600181928685015181550194019201610252565b60035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f830160051c810191602084106102fc575b601f0160051c01905b8181106102f15750610098565b5f81556001016102e4565b90915081906102db565b90607f1690610086565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761022357604052565b81601f82011215610310578051906001600160401b03821161022357610368601f8301601f1916602001610314565b928284526020838301011161031057815f9260208093018386015e830101529056fe6080806040526004361015610012575f80fd5b5f3560e01c90816306fdde03146106ab57508063095ea7b31461061c57806318160ddd146105ff57806323b872dd14610489578063313ce5671461046e57806340c10f19146102ec57806370a08231146102a857806395d89b411461012d578063a9059cbb146100fc5763dd62ed3e1461008a575f80fd5b346100f85760406003193601126100f8576100a36107ac565b73ffffffffffffffffffffffffffffffffffffffff6100c06107cf565b91165f52600160205273ffffffffffffffffffffffffffffffffffffffff60405f2091165f52602052602060405f2054604051908152f35b5f80fd5b346100f85760406003193601126100f8576101226101186107ac565b60243590336107f2565b602060405160018152f35b346100f8575f6003193601126100f8576040515f600454908160011c6001831692831561029e575b60208210841461027157818552849390811561022f57506001146101d3575b5003601f01601f191681019067ffffffffffffffff8211818310176101a6576101a282918260405282610782565b0390f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60045f90815291507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8183106102135750508101602001601f19610174565b60209193508060019154838588010152019101909183926101fd565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660208581019190915291151560051b84019091019150601f199050610174565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b90607f1690610155565b346100f85760206003193601126100f85773ffffffffffffffffffffffffffffffffffffffff6102d66107ac565b165f525f602052602060405f2054604051908152f35b346100f85760406003193601126100f8576103056107ac565b6024359073ffffffffffffffffffffffffffffffffffffffff82116103ea5773ffffffffffffffffffffffffffffffffffffffff169081156103be57600254908082018092116103915760207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef915f9360025584845283825260408420818154019055604051908152a3005b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7fec442f05000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4572726f723a206d6178206d696e7420616d6f756e742069732075696e74313660448201527f30206d61780000000000000000000000000000000000000000000000000000006064820152fd5b346100f8575f6003193601126100f857602060405160128152f35b346100f85760606003193601126100f8576104a26107ac565b6104aa6107cf565b6044359073ffffffffffffffffffffffffffffffffffffffff831692835f52600160205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260405f20547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110610526575b5061012293506107f2565b8381106105cb57841561059f57331561057357610122945f52600160205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f526020528360405f20910390558461051b565b7f94280d62000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b7fe602df05000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b83907ffb8f41b2000000000000000000000000000000000000000000000000000000005f523360045260245260445260645ffd5b346100f8575f6003193601126100f8576020600254604051908152f35b346100f85760406003193601126100f8576106356107ac565b60243590331561059f5773ffffffffffffffffffffffffffffffffffffffff1690811561057357335f52600160205260405f20825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b346100f8575f6003193601126100f8575f600354908160011c60018316928315610778575b60208210841461027157818552849390811561022f575060011461071c575003601f01601f191681019067ffffffffffffffff8211818310176101a6576101a282918260405282610782565b60035f90815291507fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b81831061075c5750508101602001601f19610174565b6020919350806001915483858801015201910190918392610746565b90607f16906106d0565b601f19601f602060409481855280519182918282880152018686015e5f8582860101520116010190565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036100f857565b6024359073ffffffffffffffffffffffffffffffffffffffff821682036100f857565b73ffffffffffffffffffffffffffffffffffffffff169081156108bc5773ffffffffffffffffffffffffffffffffffffffff169182156103be57815f525f60205260405f205481811061088a57817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b827fe450d38c000000000000000000000000000000000000000000000000000000005f5260045260245260445260645ffd5b7f96c6fd1e000000000000000000000000000000000000000000000000000000005f525f60045260245ffdfea164736f6c634300081a000a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000844656d6f5553444300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045553444300000000000000000000000000000000000000000000000000000000" + }, + { + "transactionType": "CREATE", + "address": "0x0766798566d1f6e2f0b126f7783aab2cbb81c66f", + "initCode": "0x60806040523461031057610c808038038061001981610314565b9283398101906040818303126103105780516001600160401b0381116103105782610045918301610339565b60208201519092906001600160401b038111610310576100659201610339565b81516001600160401b03811161022357600354600181811c91168015610306575b602082101461020557601f81116102a3575b50602092601f821160011461024257928192935f92610237575b50508160011b915f199060031b1c1916176003555b80516001600160401b03811161022357600454600181811c91168015610219575b602082101461020557601f81116101a2575b50602091601f8211600114610142579181925f92610137575b50508160011b915f199060031b1c1916176004555b6040516108f5908161038b8239f35b015190505f80610113565b601f1982169260045f52805f20915f5b85811061018a57508360019510610172575b505050811b01600455610128565b01515f1960f88460031b161c191690555f8080610164565b91926020600181928685015181550194019201610152565b60045f527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f830160051c810191602084106101fb575b601f0160051c01905b8181106101f057506100fa565b5f81556001016101e3565b90915081906101da565b634e487b7160e01b5f52602260045260245ffd5b90607f16906100e8565b634e487b7160e01b5f52604160045260245ffd5b015190505f806100b2565b601f1982169360035f52805f20915f5b86811061028b5750836001959610610273575b505050811b016003556100c7565b01515f1960f88460031b161c191690555f8080610265565b91926020600181928685015181550194019201610252565b60035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f830160051c810191602084106102fc575b601f0160051c01905b8181106102f15750610098565b5f81556001016102e4565b90915081906102db565b90607f1690610086565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761022357604052565b81601f82011215610310578051906001600160401b03821161022357610368601f8301601f1916602001610314565b928284526020838301011161031057815f9260208093018386015e830101529056fe6080806040526004361015610012575f80fd5b5f3560e01c90816306fdde03146106ab57508063095ea7b31461061c57806318160ddd146105ff57806323b872dd14610489578063313ce5671461046e57806340c10f19146102ec57806370a08231146102a857806395d89b411461012d578063a9059cbb146100fc5763dd62ed3e1461008a575f80fd5b346100f85760406003193601126100f8576100a36107ac565b73ffffffffffffffffffffffffffffffffffffffff6100c06107cf565b91165f52600160205273ffffffffffffffffffffffffffffffffffffffff60405f2091165f52602052602060405f2054604051908152f35b5f80fd5b346100f85760406003193601126100f8576101226101186107ac565b60243590336107f2565b602060405160018152f35b346100f8575f6003193601126100f8576040515f600454908160011c6001831692831561029e575b60208210841461027157818552849390811561022f57506001146101d3575b5003601f01601f191681019067ffffffffffffffff8211818310176101a6576101a282918260405282610782565b0390f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60045f90815291507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8183106102135750508101602001601f19610174565b60209193508060019154838588010152019101909183926101fd565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660208581019190915291151560051b84019091019150601f199050610174565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b90607f1690610155565b346100f85760206003193601126100f85773ffffffffffffffffffffffffffffffffffffffff6102d66107ac565b165f525f602052602060405f2054604051908152f35b346100f85760406003193601126100f8576103056107ac565b6024359073ffffffffffffffffffffffffffffffffffffffff82116103ea5773ffffffffffffffffffffffffffffffffffffffff169081156103be57600254908082018092116103915760207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef915f9360025584845283825260408420818154019055604051908152a3005b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7fec442f05000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4572726f723a206d6178206d696e7420616d6f756e742069732075696e74313660448201527f30206d61780000000000000000000000000000000000000000000000000000006064820152fd5b346100f8575f6003193601126100f857602060405160128152f35b346100f85760606003193601126100f8576104a26107ac565b6104aa6107cf565b6044359073ffffffffffffffffffffffffffffffffffffffff831692835f52600160205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260405f20547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110610526575b5061012293506107f2565b8381106105cb57841561059f57331561057357610122945f52600160205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f526020528360405f20910390558461051b565b7f94280d62000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b7fe602df05000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b83907ffb8f41b2000000000000000000000000000000000000000000000000000000005f523360045260245260445260645ffd5b346100f8575f6003193601126100f8576020600254604051908152f35b346100f85760406003193601126100f8576106356107ac565b60243590331561059f5773ffffffffffffffffffffffffffffffffffffffff1690811561057357335f52600160205260405f20825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b346100f8575f6003193601126100f8575f600354908160011c60018316928315610778575b60208210841461027157818552849390811561022f575060011461071c575003601f01601f191681019067ffffffffffffffff8211818310176101a6576101a282918260405282610782565b60035f90815291507fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b81831061075c5750508101602001601f19610174565b6020919350806001915483858801015201910190918392610746565b90607f16906106d0565b601f19601f602060409481855280519182918282880152018686015e5f8582860101520116010190565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036100f857565b6024359073ffffffffffffffffffffffffffffffffffffffff821682036100f857565b73ffffffffffffffffffffffffffffffffffffffff169081156108bc5773ffffffffffffffffffffffffffffffffffffffff169182156103be57815f525f60205260405f205481811061088a57817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b827fe450d38c000000000000000000000000000000000000000000000000000000005f5260045260245260445260645ffd5b7f96c6fd1e000000000000000000000000000000000000000000000000000000005f525f60045260245ffdfea164736f6c634300081a000a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000844656d6f5745544800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045745544800000000000000000000000000000000000000000000000000000000" + } + ], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x1a1af8", + "logs": [ + { + "address": "0xcff7c6da719408113dfcb5e36182c6d5aa491443", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000b0aec4c25e8332256a91bbaf169e3c32dfc3c33c" + ], + "data": "0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff", + "blockHash": "0xc33eaf631249438f553459832fb6d174cc5eaca0fceff7d63dc67019651dae57", + "blockNumber": "0x793495", + "blockTimestamp": "0x678174e5", + "transactionHash": "0xff3fd4a479bc16ce127103e5b292c041e10b7fbb9791b5a1420016d04c89ec23", + "transactionIndex": "0x1", + "logIndex": "0x0", + "removed": false + }, + { + "address": "0x0766798566d1f6e2f0b126f7783aab2cbb81c66f", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000b0aec4c25e8332256a91bbaf169e3c32dfc3c33c" + ], + "data": "0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff", + "blockHash": "0xc33eaf631249438f553459832fb6d174cc5eaca0fceff7d63dc67019651dae57", + "blockNumber": "0x793495", + "blockTimestamp": "0x678174e5", + "transactionHash": "0xff3fd4a479bc16ce127103e5b292c041e10b7fbb9791b5a1420016d04c89ec23", + "transactionIndex": "0x1", + "logIndex": "0x1", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000020000000000000000000200000000000000000000000000000000000000000000000001000000000000000000000000000000000000008000000000000000000008000000000000000000000000000020001000000000000000800000000000000000000000010000000000000001000000000000000000000000000400000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xff3fd4a479bc16ce127103e5b292c041e10b7fbb9791b5a1420016d04c89ec23", + "transactionIndex": "0x1", + "blockHash": "0xc33eaf631249438f553459832fb6d174cc5eaca0fceff7d63dc67019651dae57", + "blockNumber": "0x793495", + "gasUsed": "0x196faa", + "effectiveGasPrice": "0xfd", + "from": "0xddf32240b4ca3184de7ec8f0d5aba27dec8b7a5c", + "to": "0x4e59b44847b379578588920ca78fbf26c0b4956c", + "contractAddress": "0xb0aec4c25e8332256a91bbaf169e3c32dfc3c33c", + "l1BaseFeeScalar": "0xa6fe0", + "l1BlobBaseFee": "0x63f363e9", + "l1BlobBaseFeeScalar": "0x0", + "l1Fee": "0x33cde391b2e5", + "l1GasPrice": "0x7bbcf3e6", + "l1GasUsed": "0x9cb1" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1736537366, + "chain": 911867, + "commit": "ae9c0028" +} \ No newline at end of file diff --git a/examples/ui-demo/contracts/config/slither.config.json b/examples/ui-demo/contracts/config/slither.config.json new file mode 100644 index 0000000000..06744d9093 --- /dev/null +++ b/examples/ui-demo/contracts/config/slither.config.json @@ -0,0 +1,3 @@ +{ + "filter_paths": "(lib/|test/)" +} \ No newline at end of file diff --git a/examples/ui-demo/contracts/config/solhint-script.json b/examples/ui-demo/contracts/config/solhint-script.json new file mode 100644 index 0000000000..fecaf705b3 --- /dev/null +++ b/examples/ui-demo/contracts/config/solhint-script.json @@ -0,0 +1,21 @@ +{ + "extends": "solhint:recommended", + "rules": { + "func-name-mixedcase": "off", + "immutable-vars-naming": ["error"], + "no-unused-import": ["error"], + "compiler-version": ["error", ">=0.8.19"], + "custom-errors": "off", + "no-console": "off", + "func-visibility": ["error", { "ignoreConstructors": true }], + "max-line-length": ["error", 120], + "max-states-count": ["warn", 30], + "modifier-name-mixedcase": ["error"], + "private-vars-leading-underscore": ["error"], + "no-inline-assembly": "warn", + "avoid-low-level-calls": "off", + "one-contract-per-file": "off", + "no-empty-blocks": "off", + "reason-string": "off" + } + } \ No newline at end of file diff --git a/examples/ui-demo/contracts/config/solhint-src.json b/examples/ui-demo/contracts/config/solhint-src.json new file mode 100644 index 0000000000..b1ba809590 --- /dev/null +++ b/examples/ui-demo/contracts/config/solhint-src.json @@ -0,0 +1,17 @@ +{ + "extends": "solhint:recommended", + "rules": { + "immutable-vars-naming": ["error"], + "no-unused-import": ["error"], + "compiler-version": ["error", ">=0.8.19"], + "func-visibility": ["error", { "ignoreConstructors": true }], + "max-line-length": ["error", 120], + "func-param-name-mixedcase": ["error"], + "modifier-name-mixedcase": ["error"], + "private-vars-leading-underscore": ["error"], + "ordering": ["warn"], + "no-inline-assembly": "off", + "avoid-low-level-calls": "off", + "no-complex-fallback": "off" + } + } \ No newline at end of file diff --git a/examples/ui-demo/contracts/config/solhint-test.json b/examples/ui-demo/contracts/config/solhint-test.json new file mode 100644 index 0000000000..20ee72c88d --- /dev/null +++ b/examples/ui-demo/contracts/config/solhint-test.json @@ -0,0 +1,20 @@ +{ + "extends": "solhint:recommended", + "rules": { + "func-name-mixedcase": "off", + "immutable-vars-naming": ["error"], + "no-unused-import": ["error"], + "compiler-version": ["error", ">=0.8.19"], + "custom-errors": "off", + "func-visibility": ["error", { "ignoreConstructors": true }], + "max-line-length": ["error", 120], + "max-states-count": ["warn", 30], + "modifier-name-mixedcase": ["error"], + "private-vars-leading-underscore": ["error"], + "no-inline-assembly": "off", + "avoid-low-level-calls": "off", + "one-contract-per-file": "off", + "no-empty-blocks": "off", + "reason-string": ["warn", { "maxLength": 64 }] + } +} \ No newline at end of file diff --git a/examples/ui-demo/contracts/foundry.toml b/examples/ui-demo/contracts/foundry.toml new file mode 100644 index 0000000000..de2246cc5d --- /dev/null +++ b/examples/ui-demo/contracts/foundry.toml @@ -0,0 +1,58 @@ +[profile.default] +solc = '0.8.26' +via_ir = false +src = 'src' +test = 'test' +libs = ['lib'] +out = 'out' +optimizer = true +optimizer_runs = 200 +auto_detect_solc = false +bytecode_hash = "none" +auto_detect_remappings = false +fs_permissions = [ + { access = "read", path = "./out-optimized" } +] + +[fuzz] +runs = 500 + +[invariant] +runs=500 +fail_on_revert = true +depth = 10 + +[profile.optimized-build] +via_ir = true +test = 'src' +optimizer_runs = 10000 +out = 'out-optimized' + +[profile.optimized-test] +src = 'test' + +[profile.optimized-test-deep] +src = 'test' + +[profile.optimized-test-deep.fuzz] +runs = 10000 + +[profile.optimized-test-deep.invariant] +runs = 5000 +depth = 32 + +[profile.deep.fuzz] +runs = 100000 + +[profile.deep.invariant] +runs = 5000 +depth = 32 + +[fmt] +line_length = 115 +wrap_comments = true +sort_imports = true +number_underscore = "thousands" +int_types = "long" + +# See more config options https://github.com/foundry-rs/foundry/tree/master/config \ No newline at end of file diff --git a/examples/ui-demo/contracts/lib/forge-std b/examples/ui-demo/contracts/lib/forge-std new file mode 160000 index 0000000000..b93cf4bc34 --- /dev/null +++ b/examples/ui-demo/contracts/lib/forge-std @@ -0,0 +1 @@ +Subproject commit b93cf4bc34ff214c099dc970b153f85ade8c9f66 diff --git a/examples/ui-demo/contracts/lib/openzeppelin-contracts b/examples/ui-demo/contracts/lib/openzeppelin-contracts new file mode 160000 index 0000000000..acd4ff74de --- /dev/null +++ b/examples/ui-demo/contracts/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit acd4ff74de833399287ed6b31b4debf6b2b35527 diff --git a/examples/ui-demo/contracts/package.json b/examples/ui-demo/contracts/package.json new file mode 100644 index 0000000000..eff455a523 --- /dev/null +++ b/examples/ui-demo/contracts/package.json @@ -0,0 +1,12 @@ +{ + "devDependencies": { + "pnpm": "^8.7.5", + "solhint": "^3.6.2" + }, + "scripts": { + "lint": "pnpm lint:src && pnpm lint:test && pnpm lint:script", + "lint:src": "solhint --max-warnings 0 -c .solhint-src.json './src/**/*.sol'", + "lint:test": "solhint --max-warnings 0 -c .solhint-test.json './test/**/*.sol'", + "lint:script": "solhint --max-warnings 0 -c .solhint-script.json './script/**/*.sol'" + } + } \ No newline at end of file diff --git a/examples/ui-demo/contracts/pnpm-lock.yaml b/examples/ui-demo/contracts/pnpm-lock.yaml new file mode 100644 index 0000000000..c011cb5a17 --- /dev/null +++ b/examples/ui-demo/contracts/pnpm-lock.yaml @@ -0,0 +1,489 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + pnpm: + specifier: ^8.7.5 + version: 8.15.9 + solhint: + specifier: ^3.6.2 + version: 3.6.2 + +packages: + + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + + '@solidity-parser/parser@0.16.2': + resolution: {integrity: sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==} + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + antlr4@4.13.2: + resolution: {integrity: sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg==} + engines: {node: '>=16'} + + antlr4ts@0.5.0-alpha.4: + resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + ast-parents@0.0.1: + resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + cosmiconfig@8.3.6: + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-uri@3.0.5: + resolution: {integrity: sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + deprecated: Glob versions prior to v9 are no longer supported + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + pnpm@8.15.9: + resolution: {integrity: sha512-SZQ0ydj90aJ5Tr9FUrOyXApjOrzuW7Fee13pDzL0e1E6ypjNXP0AHDHw20VLw4BO3M1XhQHkyik6aBYWa72fgQ==} + engines: {node: '>=16.14'} + hasBin: true + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + + solhint@3.6.2: + resolution: {integrity: sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ==} + hasBin: true + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + table@6.9.0: + resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} + engines: {node: '>=10.0.0'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + +snapshots: + + '@babel/code-frame@7.26.2': + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/helper-validator-identifier@7.25.9': {} + + '@solidity-parser/parser@0.16.2': + dependencies: + antlr4ts: 0.5.0-alpha.4 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.5 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + antlr4@4.13.2: {} + + antlr4ts@0.5.0-alpha.4: {} + + argparse@2.0.1: {} + + ast-parents@0.0.1: {} + + astral-regex@2.0.0: {} + + balanced-match@1.0.2: {} + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + callsites@3.1.0: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + commander@10.0.1: {} + + cosmiconfig@8.3.6: + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + + emoji-regex@8.0.0: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + fast-deep-equal@3.1.3: {} + + fast-diff@1.3.0: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-uri@3.0.5: {} + + fs.realpath@1.0.0: {} + + glob@8.1.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + + has-flag@4.0.0: {} + + ignore@5.3.2: {} + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + is-arrayish@0.2.1: {} + + is-fullwidth-code-point@3.0.0: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + lines-and-columns@1.2.4: {} + + lodash.truncate@4.4.2: {} + + lodash@4.17.21: {} + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.26.2 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + path-type@4.0.0: {} + + picocolors@1.1.1: {} + + pluralize@8.0.0: {} + + pnpm@8.15.9: {} + + prettier@2.8.8: + optional: true + + punycode@2.3.1: {} + + require-from-string@2.0.2: {} + + resolve-from@4.0.0: {} + + semver@7.6.3: {} + + slice-ansi@4.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + solhint@3.6.2: + dependencies: + '@solidity-parser/parser': 0.16.2 + ajv: 6.12.6 + antlr4: 4.13.2 + ast-parents: 0.0.1 + chalk: 4.1.2 + commander: 10.0.1 + cosmiconfig: 8.3.6 + fast-diff: 1.3.0 + glob: 8.1.0 + ignore: 5.3.2 + js-yaml: 4.1.0 + lodash: 4.17.21 + pluralize: 8.0.0 + semver: 7.6.3 + strip-ansi: 6.0.1 + table: 6.9.0 + text-table: 0.2.0 + optionalDependencies: + prettier: 2.8.8 + transitivePeerDependencies: + - typescript + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + table@6.9.0: + dependencies: + ajv: 8.17.1 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + text-table@0.2.0: {} + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + wrappy@1.0.2: {} diff --git a/examples/ui-demo/contracts/remappings.txt b/examples/ui-demo/contracts/remappings.txt new file mode 100644 index 0000000000..eaaeb4f11d --- /dev/null +++ b/examples/ui-demo/contracts/remappings.txt @@ -0,0 +1,3 @@ +ds-test/=lib/forge-std/lib/ds-test/src/ +forge-std/=lib/forge-std/src/ +@openzeppelin/contracts=lib/openzeppelin-contracts/contracts/ \ No newline at end of file diff --git a/examples/ui-demo/contracts/script/Counter.s.sol b/examples/ui-demo/contracts/script/Counter.s.sol new file mode 100644 index 0000000000..cdc1fe9a1b --- /dev/null +++ b/examples/ui-demo/contracts/script/Counter.s.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {Script, console} from "forge-std/Script.sol"; +import {Counter} from "../src/Counter.sol"; + +contract CounterScript is Script { + Counter public counter; + + function setUp() public {} + + function run() public { + vm.startBroadcast(); + + counter = new Counter(); + + vm.stopBroadcast(); + } +} diff --git a/examples/ui-demo/contracts/script/DeployNFT.s.sol b/examples/ui-demo/contracts/script/DeployNFT.s.sol new file mode 100644 index 0000000000..c1a1411ef8 --- /dev/null +++ b/examples/ui-demo/contracts/script/DeployNFT.s.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.26; + +import {Script, console} from "forge-std/Script.sol"; + +import {NFT} from "../src/NFT.sol"; + +contract DeployNFTScript is Script { + + function run() public { + + string memory name = "Account Kit Demo NFT"; + string memory symbol = "AKD"; + string memory baseURI = "https://static.alchemyapi.io/assets/accountkit/accountkit.jpg"; + + vm.startBroadcast(); + + NFT nft = new NFT{ salt: 0 }(name, symbol, baseURI); + + console.log("NFT deployed at address: ", address(nft)); + + vm.stopBroadcast(); + } +} \ No newline at end of file diff --git a/examples/ui-demo/contracts/script/DeploySwapVenue.s.sol b/examples/ui-demo/contracts/script/DeploySwapVenue.s.sol new file mode 100644 index 0000000000..a821934f75 --- /dev/null +++ b/examples/ui-demo/contracts/script/DeploySwapVenue.s.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {Script, console} from "forge-std/Script.sol"; +import {Swap} from "../src/Swap.sol"; + +contract DeploySwapVenueScript is Script { + + function run() public { + vm.startBroadcast(); + + Swap swap = new Swap{ salt: 0 }(); + + console.log("Swap deployed at address: ", address(swap)); + + vm.stopBroadcast(); + } +} diff --git a/examples/ui-demo/contracts/src/Counter.sol b/examples/ui-demo/contracts/src/Counter.sol new file mode 100644 index 0000000000..aded7997b0 --- /dev/null +++ b/examples/ui-demo/contracts/src/Counter.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +contract Counter { + uint256 public number; + + function setNumber(uint256 newNumber) public { + number = newNumber; + } + + function increment() public { + number++; + } +} diff --git a/examples/ui-demo/contracts/src/ERC20Mintable.sol b/examples/ui-demo/contracts/src/ERC20Mintable.sol new file mode 100644 index 0000000000..92904e2503 --- /dev/null +++ b/examples/ui-demo/contracts/src/ERC20Mintable.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; + +contract ERC20Mintable is ERC20 { + constructor(string memory name, string memory symbol) + ERC20(name, symbol) + {} + + function mint(address to, uint256 amount) public { + require(amount <= type(uint160).max, "Error: max mint amount is uint160 max"); + _mint(to, amount); + } +} \ No newline at end of file diff --git a/examples/ui-demo/contracts/src/NFT.sol b/examples/ui-demo/contracts/src/NFT.sol new file mode 100644 index 0000000000..8e8aed488f --- /dev/null +++ b/examples/ui-demo/contracts/src/NFT.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; + +error NonExistentTokenURI(); + +contract NFT is ERC721 { + + using Strings for uint256; + string public baseURI; + uint256 public currentTokenId; + + constructor( + string memory _name, + string memory _symbol, + string memory _baseURI + ) ERC721(_name, _symbol) { + baseURI = _baseURI; + } + + function mintTo(address recipient) public payable returns (uint256) { + uint256 newTokenId = ++currentTokenId; + _safeMint(recipient, newTokenId); + return newTokenId; + } + + function tokenURI(uint256 tokenId) + public + view + virtual + override + returns (string memory) + { + if (ownerOf(tokenId) == address(0)) { + revert NonExistentTokenURI(); + } + return baseURI; + } +} \ No newline at end of file diff --git a/examples/ui-demo/contracts/src/Swap.sol b/examples/ui-demo/contracts/src/Swap.sol new file mode 100644 index 0000000000..b7579e5aff --- /dev/null +++ b/examples/ui-demo/contracts/src/Swap.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import {ERC20Mintable} from "./ERC20Mintable.sol"; + +contract Swap { + ERC20Mintable public usdc; + ERC20Mintable public weth; + + constructor() { + usdc = new ERC20Mintable("DemoUSDC", "USDC"); + usdc.mint(address(this), type(uint160).max); + + weth = new ERC20Mintable("DemoWETH", "WETH"); + weth.mint(address(this), type(uint160).max); + } + + function mint(uint amount1, uint amount2) external { + usdc.mint(msg.sender, amount1); + weth.mint(msg.sender, amount2); + } + + function swapUSDCtoWETH(uint amountIn, uint amountOut) external { + require(amountOut <= 10 ether, "Max 10 eth swap at a time"); + usdc.transferFrom(msg.sender, address(this), amountIn); + weth.transfer(msg.sender, amountOut); + } + + function swapWETHtoUSDC(uint amountIn, uint amountOut) external { + require(amountOut <= 100000 ether, "Max 100k USDC swap at a time"); + weth.transferFrom(msg.sender, address(this), amountIn); + usdc.transfer(msg.sender, amountOut); + } +} \ No newline at end of file diff --git a/examples/ui-demo/contracts/test/Counter.t.sol b/examples/ui-demo/contracts/test/Counter.t.sol new file mode 100644 index 0000000000..54b724f7ae --- /dev/null +++ b/examples/ui-demo/contracts/test/Counter.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {Test, console} from "forge-std/Test.sol"; +import {Counter} from "../src/Counter.sol"; + +contract CounterTest is Test { + Counter public counter; + + function setUp() public { + counter = new Counter(); + counter.setNumber(0); + } + + function test_Increment() public { + counter.increment(); + assertEq(counter.number(), 1); + } + + function testFuzz_SetNumber(uint256 x) public { + counter.setNumber(x); + assertEq(counter.number(), x); + } +} diff --git a/examples/ui-demo/env.mjs b/examples/ui-demo/env.mjs index c2014c028e..1ece531008 100644 --- a/examples/ui-demo/env.mjs +++ b/examples/ui-demo/env.mjs @@ -11,6 +11,7 @@ export const env = createEnv({ API_KEY: z.string(), ALCHEMY_API_URL: z.string().url(), ALCHEMY_RPC_URL: z.string().url(), + ALCHEMY_RPC_URL_ODYSSEY: z.string().url(), }, /** @@ -29,5 +30,6 @@ export const env = createEnv({ API_KEY: process.env.API_KEY, ALCHEMY_API_URL: process.env.ALCHEMY_API_URL, ALCHEMY_RPC_URL: process.env.ALCHEMY_RPC_URL, + ALCHEMY_RPC_URL_ODYSSEY: process.env.ALCHEMY_RPC_URL_ODYSSEY, }, }); diff --git a/examples/ui-demo/package.json b/examples/ui-demo/package.json index 19af52f773..7f8784e139 100644 --- a/examples/ui-demo/package.json +++ b/examples/ui-demo/package.json @@ -34,7 +34,7 @@ "react-dom": "^18", "react-syntax-highlighter": "^15.5.0", "tailwind-merge": "^2.3.0", - "viem": "^2.20.0", + "viem": "^2.22.6", "wagmi": "^2.12.7", "zod": "^3.0.0", "zustand": "^5.0.0-rc.2" diff --git a/examples/ui-demo/src/app/api/bundler-odyssey/route.ts b/examples/ui-demo/src/app/api/bundler-odyssey/route.ts new file mode 100644 index 0000000000..3e6bb584ff --- /dev/null +++ b/examples/ui-demo/src/app/api/bundler-odyssey/route.ts @@ -0,0 +1,30 @@ +import { NextRequest, NextResponse } from "next/server"; + +import { env } from "../../../../env.mjs"; + +export async function POST(req: NextRequest) { + const body = await req.text(); + const headers: Record = {}; + req.headers.forEach((value, key) => { + // don't pass the cookie because it doesn't get used downstream + if (key === "cookie") return; + + headers[key] = value; + }); + + const res = await fetch(env.ALCHEMY_RPC_URL_ODYSSEY, { + method: "POST", + headers: { + ...headers, + }, + body, + }); + + if (!res.ok) { + return NextResponse.json(await res.json().catch((e) => ({})), { + status: res.status, + }); + } + + return NextResponse.json(await res.json()); +} diff --git a/examples/ui-demo/src/app/config.tsx b/examples/ui-demo/src/app/config.tsx index d827762cf8..176447f23e 100644 --- a/examples/ui-demo/src/app/config.tsx +++ b/examples/ui-demo/src/app/config.tsx @@ -36,9 +36,15 @@ export type Config = { } | undefined; }; + walletType: WalletTypes; supportUrl?: string; }; +export enum WalletTypes { + smart = "smart", + hybrid7702 = "7702", +} + export const DEFAULT_CONFIG: Config = { auth: { showEmail: true, @@ -65,6 +71,7 @@ export const DEFAULT_CONFIG: Config = { logoLight: undefined, logoDark: undefined, }, + walletType: WalletTypes.smart, }; export const queryClient = new QueryClient(); diff --git a/examples/ui-demo/src/app/page.tsx b/examples/ui-demo/src/app/page.tsx index 0a8b799485..2f79bf0bb3 100644 --- a/examples/ui-demo/src/app/page.tsx +++ b/examples/ui-demo/src/app/page.tsx @@ -20,6 +20,10 @@ import { AuthCardWrapper } from "../components/preview/AuthCardWrapper"; import { CodePreview } from "../components/preview/CodePreview"; import { CodePreviewSwitch } from "../components/shared/CodePreviewSwitch"; import { TopNav } from "../components/topnav/TopNav"; +import { Configuration } from "@/components/configuration/Configuration"; +import { Wrapper7702 } from "@/components/shared/7702/Wrapper"; +import { useConfigStore } from "@/state"; +import { WalletTypes } from "./config"; const publicSans = Public_Sans({ subsets: ["latin"], @@ -36,6 +40,7 @@ export default function Home() { const user = useUser(); const theme = useTheme(); const isEOAUser = user?.type === "eoa"; + const { walletType } = useConfigStore(); return (
+
@@ -128,21 +134,44 @@ export default function Home() {
- {!user && } - {isEOAUser && ( -
-
- -
- - -
-
-
- )} - {user && !isEOAUser && } +
); } + +const RenderContent = ({ + user, + isEOAUser, + isSmartWallet, +}: { + user: boolean; + isEOAUser: boolean; + isSmartWallet: boolean; +}) => { + if (!user) { + return ; + } + if (isEOAUser) { + return ( +
+
+ +
+ + +
+
+
+ ); + } + if (isSmartWallet) { + return ; + } + return ; +}; diff --git a/examples/ui-demo/src/components/configuration/Configuration.tsx b/examples/ui-demo/src/components/configuration/Configuration.tsx new file mode 100644 index 0000000000..1b471a08e4 --- /dev/null +++ b/examples/ui-demo/src/components/configuration/Configuration.tsx @@ -0,0 +1,53 @@ +// import { useState } from "react"; +import { cn } from "@/lib/utils"; + +import { SettingsIcon } from "../icons/settings"; +// import { HelpTooltip } from "../shared/HelpTooltip"; +import { WalletTypeSwitch } from "../shared/WalletTypeSwitch"; +import ExternalLink from "../shared/ExternalLink"; +import { useConfigStore } from "@/state"; +import { WalletTypes } from "@/app/config"; + +export const Configuration = ({ className }: { className?: string }) => { + const { setWalletType, walletType } = useConfigStore(); + // const [walletType, setWalletType] = useState(WalletTypes.smart); + + const onSwitchWalletType = () => { + setWalletType( + walletType === WalletTypes.smart + ? WalletTypes.hybrid7702 + : WalletTypes.smart + ); + }; + + return ( +
+
+ + Configuration +
+
+

+ Embedded Wallet Type +

+ {/* */} +
+ +

+ Sentence describing all of the value props fo 7702 and educating the + user. Curious about what this means? + + Learn more. + +

+
+
+ ); +}; diff --git a/examples/ui-demo/src/components/icons/key.tsx b/examples/ui-demo/src/components/icons/key.tsx new file mode 100644 index 0000000000..366380ad26 --- /dev/null +++ b/examples/ui-demo/src/components/icons/key.tsx @@ -0,0 +1,24 @@ +export const Key = ({ className }: { className?: string }) => ( + + + + +); diff --git a/examples/ui-demo/src/components/icons/loading.tsx b/examples/ui-demo/src/components/icons/loading.tsx index ef89746f77..eb5041e0d8 100644 --- a/examples/ui-demo/src/components/icons/loading.tsx +++ b/examples/ui-demo/src/components/icons/loading.tsx @@ -1,5 +1,5 @@ import { useTheme } from "@/state/useTheme"; -export const LoadingIcon = () => { +export const LoadingIcon = ({ className }: { className?: string }) => { const theme = useTheme(); const animationClass = theme === "dark" ? "animate-ui-loading-dark" : "animate-ui-loading-light"; @@ -11,6 +11,7 @@ export const LoadingIcon = () => { viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" + className={className} > ) => ( + + + +); diff --git a/examples/ui-demo/src/components/preview/AuthCardWrapper.tsx b/examples/ui-demo/src/components/preview/AuthCardWrapper.tsx index 9b94e30120..38d6962f23 100644 --- a/examples/ui-demo/src/components/preview/AuthCardWrapper.tsx +++ b/examples/ui-demo/src/components/preview/AuthCardWrapper.tsx @@ -4,6 +4,9 @@ import { cn } from "@/lib/utils"; import { useTheme } from "@/state/useTheme"; import { AuthCard, useUser } from "@account-kit/react"; import { EOAPostLogin } from "../shared/eoa-post-login/EOAPostLogin"; +import { Wrapper7702 } from "../shared/7702/Wrapper"; +import { useConfigStore } from "@/state"; +import { WalletTypes } from "@/app/config"; import { MintCard } from "../shared/mint-card/MintCard"; export function AuthCardWrapper({ className }: { className?: string }) { @@ -25,6 +28,7 @@ export function AuthCardWrapper({ className }: { className?: string }) { } const RenderContent = () => { + const { walletType } = useConfigStore(); const user = useUser(); const hasUser = !!user; @@ -54,5 +58,5 @@ const RenderContent = () => { ); } - return ; + return walletType === WalletTypes.smart ? : ; }; diff --git a/examples/ui-demo/src/components/shared/7702/Button.tsx b/examples/ui-demo/src/components/shared/7702/Button.tsx new file mode 100644 index 0000000000..6d19275a90 --- /dev/null +++ b/examples/ui-demo/src/components/shared/7702/Button.tsx @@ -0,0 +1,18 @@ +import { PropsWithChildren } from "react"; + +export const Button = ({ + children, + className, + ...rest +}: PropsWithChildren< + React.ComponentProps<"button"> & { className?: string } +>) => { + return ( + + ); +}; diff --git a/examples/ui-demo/src/components/shared/7702/Debug7702Button.tsx b/examples/ui-demo/src/components/shared/7702/Debug7702Button.tsx new file mode 100644 index 0000000000..35dafcb590 --- /dev/null +++ b/examples/ui-demo/src/components/shared/7702/Debug7702Button.tsx @@ -0,0 +1,125 @@ +"use client"; + +import { Button } from "../Button"; +// import { +// useSmartAccountClient, +// } from "@account-kit/react"; +import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; +import { createPublicClient, toRlp, fromRlp } from "viem"; +import { + createBundlerClientFromExisting, + LocalAccountSigner, +} from "@aa-sdk/core"; +import { odyssey, splitOdysseyTransport } from "./transportSetup"; +import { send7702UO } from "./demoSend7702UO"; +import { useSigner } from "@account-kit/react"; + +export const Debug7702Button = () => { + // const { client, address, isLoadingClient } = useSmartAccountClient({ + // type: "LightAccount", + // }); + + const signer = useSigner(); + + const runFunc = async (local: boolean) => { + const publicClient = createPublicClient({ + chain: odyssey, + transport: splitOdysseyTransport, + }); + + // console.log("reported chain id: ", await publicClient.getChainId()); + + // console.log( + // "reported balance: ", + // await publicClient.getBalance({ address: localAccount.address }) + // ); + + const bundlerClient = createBundlerClientFromExisting(publicClient); + + // console.log( + // "supported entry points: ", + // await bundlerClient.getSupportedEntryPoints() + // ); + + // const tprt = splitMekongTransport({ chain: mekong }); + + // const res = tprt.request({ + // method: "rundler_maxPriorityFeePerGas", + // params: [], + // }); + + // console.log("maxPriorityFeePerGas: ", await res); + + // send7702UO(bundlerClient, splitMekongTransport, new LocalAccountSigner(localAccount)); + + if (local) { + // Addr: 0xdF0C33fe84BEBdcbd1029E95295AC4D2A7Ca0f7a + // pkey: 0x18bec901c0253fbb203d3423dada59eb720c68f34935185de43d161b0524404b + const localAccount = privateKeyToAccount(generatePrivateKey()); + + send7702UO( + bundlerClient, + splitOdysseyTransport, + new LocalAccountSigner(localAccount) + ); + } else { + if (!signer) { + console.error("No signer found"); + return; + } + send7702UO(bundlerClient, splitOdysseyTransport, signer); + } + }; + + const runLocal = () => runFunc(true); + const runSigner = () => runFunc(false); + + const rlpEncode = () => { + const chain_id = "0xde9fb"; + const address = "0x69007702764179f14f51cdce752f4f775d74e139"; + const nonce = "0x"; + const yParity = "0x1c"; + const r = + "0x2943f6154757e02a7c8264f9c2f79fac321beef60578746c61eb84a5fc4525d7"; + const s = + "0x6a23e53538e028c06f5b149e33424ea11358eecec44ecd8819fbf67ceb03a957"; + + // // result: 0xf85d830de9fb9469007702764179f14f51cdce752f4f775d74e1390001a02943f6154757e02a7c8264f9c2f79fac321beef60578746c61eb84a5fc4525d7a06a23e53538e028c06f5b149e33424ea11358eecec44ecd8819fbf67ceb03a957 + // // result 2: 0xf85ff85d830de9fb9469007702764179f14f51cdce752f4f775d74e1390001a02943f6154757e02a7c8264f9c2f79fac321beef60578746c61eb84a5fc4525d7a06a23e53538e028c06f5b149e33424ea11358eecec44ecd8819fbf67ceb03a957 + // // ext result: 0xf85d830de9fb9470d37dc45141e10c42f27e432458218ed4e1aab78080a084039480ba511822433b50a1dea5738e7a946ba187172c02f00076e4a87545a1a001dc4c5f78b6c81f5a695ee8725346a45bf9d1d1f7c1437532efd31a9769fda5 + + // const chain_id = "0xde9fb"; + // const address = "0x69007702764179f14f51cdce752f4f775d74e139"; + // const nonce = "0x0"; + // const yParity = "0x1c"; + // const r = "0x2943f6154757e02a7c8264f9c2f79fac321beef60578746c61eb84a5fc4525d7"; + // const s = "0x6a23e53538e028c06f5b149e33424ea11358eecec44ecd8819fbf67ceb03a957"; + + // // result: 0xf85d830de9fb9469007702764179f14f51cdce752f4f775d74e139001ca02943f6154757e02a7c8264f9c2f79fac321beef60578746c61eb84a5fc4525d7a06a23e53538e028c06f5b149e33424ea11358eecec44ecd8819fbf67ceb03a957 + + const encoded = toRlp([chain_id, address, nonce, yParity, r, s]); + + console.log("encoded: ", encoded); + }; + + const rlpDecode = () => { + // const input = "0xf85d830de9fb9470d37dc45141e10c42f27e432458218ed4e1aab78080a084039480ba511822433b50a1dea5738e7a946ba187172c02f00076e4a87545a1a001dc4c5f78b6c81f5a695ee8725346a45bf9d1d1f7c1437532efd31a9769fda5"; + + // From cast sign-auth with the local pkey + const input = + "0xf85d830de9fb9469007702764179f14f51cdce752f4f775d74e1398080a07e650c48b0033a147681165efb7fe9b6195f64f41f71f4b8e503657fd57c3609a00ad5d521d5bbfdcda9d3b9d7b9790cd6ed695d7d63ec08ef49de9631ea0e9b25"; + + // result: + + console.log(fromRlp(input)); + }; + + return ( +
+ + + + +
+ ); +}; diff --git a/examples/ui-demo/src/components/shared/7702/MintCard7702.tsx b/examples/ui-demo/src/components/shared/7702/MintCard7702.tsx new file mode 100644 index 0000000000..1094b117b4 --- /dev/null +++ b/examples/ui-demo/src/components/shared/7702/MintCard7702.tsx @@ -0,0 +1,94 @@ +import Image from "next/image"; +import { LoadingIcon } from "@/components/icons/loading"; +import { Button } from "./Button"; +import { MintStages } from "./MintStages"; + +type NFTLoadingState = "initial" | "loading" | "success"; +export type MintStatus = { + signing: NFTLoadingState; + gas: NFTLoadingState; + batch: NFTLoadingState; +}; + +export const MintCard7702 = ({ + isLoading, + isDisabled, + status, + nftTransfered, + handleCollectNFT, + uri, +}: { + isLoading: boolean; + isDisabled?: boolean; + status: MintStatus; + nftTransfered: boolean; + handleCollectNFT: () => void; + uri?: string; +}) => { + return ( +
+ {uri ? ( +
+ An NFT +
+ ) : ( +
+ +
+ )} +
+

+ Gasless transactions +

+
+ {!nftTransfered ? ( + <> +

+ Sponsor gas and sign in the background for a one-click transaction + experience. +

+
+

Gas Fee

+

+ + $0.02 + + + Free + +

+
+ + ) : ( + + )} + +
+ ); +}; diff --git a/examples/ui-demo/src/components/shared/7702/MintStages.tsx b/examples/ui-demo/src/components/shared/7702/MintStages.tsx new file mode 100644 index 0000000000..70708d7ec0 --- /dev/null +++ b/examples/ui-demo/src/components/shared/7702/MintStages.tsx @@ -0,0 +1,52 @@ +import { CheckCircleFilledIcon } from "@/components/icons/check-circle-filled"; +import { LoadingIcon } from "@/components/icons/loading"; +import { MintStatus } from "./MintCard7702"; +import { loadingState } from "./Transactions"; + +export const MintStages = ({ status }: { status: MintStatus }) => { + return ( +
+ + + +
+ ); +}; + +const Stage = ({ + icon, + description, + className, +}: { + icon: loadingState; + description: string | JSX.Element; + className?: string; +}) => { + return ( +
+
{getMintIcon(icon)}
+

{description}

+
+ ); +}; + +export const getMintIcon = (icon: loadingState) => { + switch (icon) { + case "loading": + case "initial": + return ; + case "success": + return ( + + ); + } +}; diff --git a/examples/ui-demo/src/components/shared/7702/Transactions.tsx b/examples/ui-demo/src/components/shared/7702/Transactions.tsx new file mode 100644 index 0000000000..c4ea547ea3 --- /dev/null +++ b/examples/ui-demo/src/components/shared/7702/Transactions.tsx @@ -0,0 +1,62 @@ +import { ExternalLinkIcon } from "@/components/icons/external-link"; +import { TransactionType } from "./useTransaction"; +import { CheckCircleFilledIcon } from "@/components/icons/check-circle-filled"; +import { LoadingIcon } from "@/components/icons/loading"; + +export type loadingState = "loading" | "success" | "initial"; + +export const Transactions = ({ + transactions, +}: { + transactions: TransactionType[]; +}) => { + return ( +
+ {transactions.map((transaction, i) => ( + + ))} +
+ ); +}; + +const Transaction = ({ + className, + externalLink, + description, + state, +}: TransactionType & { className?: string }) => { + const getText = () => { + if (state === "initial") { + return "..."; + } + if (state === "initiating") { + return "Initiating buy..."; + } + if (state === "next") { + return "Next buy in 10 seconds..."; + } + return description; + }; + + return ( +
+
+
+ {state === "complete" ? ( + + ) : ( + + )} +
+

{getText()}

+
+ {externalLink && state === "complete" && ( + +
+ +
+
+ )} +
+ ); +}; diff --git a/examples/ui-demo/src/components/shared/7702/TransactionsCard.tsx b/examples/ui-demo/src/components/shared/7702/TransactionsCard.tsx new file mode 100644 index 0000000000..1828f741e5 --- /dev/null +++ b/examples/ui-demo/src/components/shared/7702/TransactionsCard.tsx @@ -0,0 +1,61 @@ +import { Key } from "@/components/icons/key"; +import { Button } from "./Button"; +import { useState } from "react"; +import { Transactions } from "./Transactions"; +import { TransactionType } from "./useTransaction"; + +export const TransactionsCard = ({ + isLoading, + isDisabled, + transactions, + handleTransactions, +}: { + isLoading: boolean; + isDisabled?: boolean; + transactions: TransactionType[]; + handleTransactions: () => void; +}) => { + const [hasClicked, setHasClicked] = useState(false); + const handleClick = () => { + setHasClicked(true); + handleTransactions(); + }; + return ( +
+
+

+ New! +

+ +
+

+ Recurring transactions +

+ {!hasClicked ? ( +

+ Set up a dollar-cost average order by creating a session key with + permission to buy ETH every 10 seconds. +

+ ) : ( + + )} + + +
+ ); +}; diff --git a/examples/ui-demo/src/components/shared/7702/Wrapper.tsx b/examples/ui-demo/src/components/shared/7702/Wrapper.tsx new file mode 100644 index 0000000000..6cfe87382a --- /dev/null +++ b/examples/ui-demo/src/components/shared/7702/Wrapper.tsx @@ -0,0 +1,40 @@ +import { RenderUserConnectionAvatar } from "../user-connection-avatar/RenderUserConnectionAvatar"; +import { MintCard7702 } from "./MintCard7702"; +import { TransactionsCard } from "./TransactionsCard"; +import { useMint } from "./useMint"; +import { useTransactions } from "./useTransaction"; + +export const Wrapper7702 = () => { + const { + isLoading: isLoadingTransactions, + transactions, + handleTransactions, + } = useTransactions(); + const { + isLoading: isLoadingMint, + status, + nftTransfered, + handleCollectNFT, + uri, + } = useMint(); + return ( +
+ + +
+ +
+ ); +}; diff --git a/examples/ui-demo/src/components/shared/7702/dca/abi/erc20Mintable.ts b/examples/ui-demo/src/components/shared/7702/dca/abi/erc20Mintable.ts new file mode 100644 index 0000000000..807101ac4c --- /dev/null +++ b/examples/ui-demo/src/components/shared/7702/dca/abi/erc20Mintable.ts @@ -0,0 +1,344 @@ +export const erc20MintableAbi = [ + { + type: "constructor", + inputs: [ + { + name: "name", + type: "string", + internalType: "string", + }, + { + name: "symbol", + type: "string", + internalType: "string", + }, + ], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "allowance", + inputs: [ + { + name: "owner", + type: "address", + internalType: "address", + }, + { + name: "spender", + type: "address", + internalType: "address", + }, + ], + outputs: [ + { + name: "", + type: "uint256", + internalType: "uint256", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "approve", + inputs: [ + { + name: "spender", + type: "address", + internalType: "address", + }, + { + name: "value", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [ + { + name: "", + type: "bool", + internalType: "bool", + }, + ], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "balanceOf", + inputs: [ + { + name: "account", + type: "address", + internalType: "address", + }, + ], + outputs: [ + { + name: "", + type: "uint256", + internalType: "uint256", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "decimals", + inputs: [], + outputs: [ + { + name: "", + type: "uint8", + internalType: "uint8", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "mint", + inputs: [ + { + name: "to", + type: "address", + internalType: "address", + }, + { + name: "amount", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "name", + inputs: [], + outputs: [ + { + name: "", + type: "string", + internalType: "string", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "symbol", + inputs: [], + outputs: [ + { + name: "", + type: "string", + internalType: "string", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "totalSupply", + inputs: [], + outputs: [ + { + name: "", + type: "uint256", + internalType: "uint256", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "transfer", + inputs: [ + { + name: "to", + type: "address", + internalType: "address", + }, + { + name: "value", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [ + { + name: "", + type: "bool", + internalType: "bool", + }, + ], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "transferFrom", + inputs: [ + { + name: "from", + type: "address", + internalType: "address", + }, + { + name: "to", + type: "address", + internalType: "address", + }, + { + name: "value", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [ + { + name: "", + type: "bool", + internalType: "bool", + }, + ], + stateMutability: "nonpayable", + }, + { + type: "event", + name: "Approval", + inputs: [ + { + name: "owner", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "spender", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "value", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "event", + name: "Transfer", + inputs: [ + { + name: "from", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "to", + type: "address", + indexed: true, + internalType: "address", + }, + { + name: "value", + type: "uint256", + indexed: false, + internalType: "uint256", + }, + ], + anonymous: false, + }, + { + type: "error", + name: "ERC20InsufficientAllowance", + inputs: [ + { + name: "spender", + type: "address", + internalType: "address", + }, + { + name: "allowance", + type: "uint256", + internalType: "uint256", + }, + { + name: "needed", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "ERC20InsufficientBalance", + inputs: [ + { + name: "sender", + type: "address", + internalType: "address", + }, + { + name: "balance", + type: "uint256", + internalType: "uint256", + }, + { + name: "needed", + type: "uint256", + internalType: "uint256", + }, + ], + }, + { + type: "error", + name: "ERC20InvalidApprover", + inputs: [ + { + name: "approver", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "ERC20InvalidReceiver", + inputs: [ + { + name: "receiver", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "ERC20InvalidSender", + inputs: [ + { + name: "sender", + type: "address", + internalType: "address", + }, + ], + }, + { + type: "error", + name: "ERC20InvalidSpender", + inputs: [ + { + name: "spender", + type: "address", + internalType: "address", + }, + ], + }, +] as const; diff --git a/examples/ui-demo/src/components/shared/7702/dca/abi/swap.ts b/examples/ui-demo/src/components/shared/7702/dca/abi/swap.ts new file mode 100644 index 0000000000..365b7d0c17 --- /dev/null +++ b/examples/ui-demo/src/components/shared/7702/dca/abi/swap.ts @@ -0,0 +1,87 @@ +export const swapAbi = [ + { + type: "constructor", + inputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "mint", + inputs: [ + { + name: "amount1", + type: "uint256", + internalType: "uint256", + }, + { + name: "amount2", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "swapUSDCtoWETH", + inputs: [ + { + name: "amountIn", + type: "uint256", + internalType: "uint256", + }, + { + name: "amountOut", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "swapWETHtoUSDC", + inputs: [ + { + name: "amountIn", + type: "uint256", + internalType: "uint256", + }, + { + name: "amountOut", + type: "uint256", + internalType: "uint256", + }, + ], + outputs: [], + stateMutability: "nonpayable", + }, + { + type: "function", + name: "usdc", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "contract ERC20Mintable", + }, + ], + stateMutability: "view", + }, + { + type: "function", + name: "weth", + inputs: [], + outputs: [ + { + name: "", + type: "address", + internalType: "contract ERC20Mintable", + }, + ], + stateMutability: "view", + }, +] as const; diff --git a/examples/ui-demo/src/components/shared/7702/dca/constants.ts b/examples/ui-demo/src/components/shared/7702/dca/constants.ts new file mode 100644 index 0000000000..56b0a37167 --- /dev/null +++ b/examples/ui-demo/src/components/shared/7702/dca/constants.ts @@ -0,0 +1,10 @@ +import type { Address } from "viem"; + +export const SWAP_VENUE_ADDRESS: Address = + "0xB0AEC4c25E8332256A91bBaf169E3C32dfC3C33C"; + +export const DEMO_USDC_ADDRESS: Address = + "0xCFf7C6dA719408113DFcb5e36182c6d5aa491443"; + +export const DEMO_WETH_ADDRESS: Address = + "0x0766798566D1f6e2f0b126f7783aaB2CBb81c66f"; diff --git a/examples/ui-demo/src/components/shared/7702/dca/sessionKeyInit.ts b/examples/ui-demo/src/components/shared/7702/dca/sessionKeyInit.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/ui-demo/src/components/shared/7702/demoSend7702UO.ts b/examples/ui-demo/src/components/shared/7702/demoSend7702UO.ts new file mode 100644 index 0000000000..835014cb49 --- /dev/null +++ b/examples/ui-demo/src/components/shared/7702/demoSend7702UO.ts @@ -0,0 +1,48 @@ +import { zeroAddress, type PublicClient } from "viem"; + +import { type SmartAccountSigner, type BundlerClient } from "@aa-sdk/core"; + +import { + alchemyFeeEstimator, + alchemyGasManagerMiddleware, + type AlchemyTransport, +} from "@account-kit/infra"; + +import { createSMA7702AccountClient } from "@account-kit/smart-contracts/experimental"; + +import { odyssey } from "./transportSetup"; + +export const send7702UO = async ( + client: PublicClient & BundlerClient, + transport: AlchemyTransport, + signer: SmartAccountSigner +) => { + // console.log( + // "supported entry points: ", + // await client.getSupportedEntryPoints() + // ); + + // console.log("reading env from client", process.env.NEXT_PUBLIC_PAYMASTER_POLICY_ID); + + const accountClient = await createSMA7702AccountClient({ + chain: odyssey, + transport, + signer, + feeEstimator: alchemyFeeEstimator(transport), + ...alchemyGasManagerMiddleware( + process.env.NEXT_PUBLIC_PAYMASTER_POLICY_ID! + ), + }); + + // const uoHash = await accountClient.sendUserOperation({ + // uo: { + // target: zeroAddress, + // data: "0x", + // value: BigInt(0), + // }, + // }); + + // const txnHash = await accountClient.waitForUserOperationTransaction(uoHash); + + // console.log("txnHash: ", txnHash); +}; diff --git a/examples/ui-demo/src/components/shared/7702/transportSetup.ts b/examples/ui-demo/src/components/shared/7702/transportSetup.ts new file mode 100644 index 0000000000..62022476f0 --- /dev/null +++ b/examples/ui-demo/src/components/shared/7702/transportSetup.ts @@ -0,0 +1,79 @@ +import type { Chain } from "viem"; +import { defineChain } from "viem"; +import { alchemy } from "@account-kit/infra"; + +// export const mekong: Chain = defineChain({ +// id: 7078815900, +// name: "Mekong Pectra Devnet", +// nativeCurrency: { name: "eth", symbol: "eth", decimals: 18 }, +// rpcUrls: { +// default: { +// http: ["https://rpc.mekong.ethpandaops.io"], +// }, +// alchemy: { +// http: ["https://rpc.mekong.ethpandaops.io"], +// }, +// }, +// blockExplorers: { +// default: { +// name: "Block Explorer", +// url: "https://explorer.mekong.ethpandaops.io", +// }, +// }, +// testnet: true, +// }); + +export const odyssey: Chain = defineChain({ + id: 911867, + name: "Odyssey", + nativeCurrency: { name: "eth", symbol: "eth", decimals: 18 }, + rpcUrls: { + default: { + http: ["https://odyssey.ithaca.xyz"], + }, + alchemy: { + http: ["https://odyssey.ithaca.xyz"], + }, + }, + blockExplorers: { + default: { + name: "Block Explorer", + url: "https://odyssey-explorer.ithaca.xyz/", + }, + }, + testnet: true, +}); + +// const bundlerMethods = [ +// "eth_sendUserOperation", +// "eth_estimateUserOperationGas", +// "eth_getUserOperationReceipt", +// "eth_getUserOperationByHash", +// "eth_supportedEntryPoints", +// "rundler_maxPriorityFeePerGas", +// ]; + +// export const splitMekongTransport = split({ +// overrides: [ +// { +// methods: bundlerMethods, +// transport: http("https://eth-mekong.g.alchemypreview.com/v2/HjEy_lTrJ0P2Y8BRFhAHm_1dVc0svdme"), +// }, +// ], +// fallback: http("/api/rpc-mekong"), +// }) + +// export const splitMekongTransport = alchemy({ +// alchemyConnection: { +// rpcUrl: +// "https://eth-mekong.g.alchemypreview.com/v2/HjEy_lTrJ0P2Y8BRFhAHm_1dVc0svdme", +// }, +// nodeRpcUrl: "/api/rpc-mekong", +// }); + +export const splitOdysseyTransport = alchemy({ + alchemyConnection: { + rpcUrl: "/api/bundler-odyssey", + }, + nodeRpcUrl: "https://odyssey.ithaca.xyz", +}); diff --git a/examples/ui-demo/src/components/shared/7702/useMint.tsx b/examples/ui-demo/src/components/shared/7702/useMint.tsx new file mode 100644 index 0000000000..be0c0072ef --- /dev/null +++ b/examples/ui-demo/src/components/shared/7702/useMint.tsx @@ -0,0 +1,117 @@ +import { + useSendUserOperation, + useSmartAccountClient, +} from "@account-kit/react"; +import { useQuery } from "@tanstack/react-query"; +import { AccountKitNftMinterABI, nftContractAddress } from "@/utils/config"; +import { useCallback, useState } from "react"; +import { useToast } from "@/hooks/useToast"; +import { encodeFunctionData } from "viem"; +import { MintStatus } from "./MintCard7702"; + +const initialValuePropState = { + signing: "initial", + gas: "initial", + batch: "initial", +} satisfies MintStatus; + +export const useMint = () => { + const [status, setStatus] = useState(initialValuePropState); + const [nftTransfered, setNftTransfered] = useState(false); + const isLoading = Object.values(status).some((x) => x === "loading"); + const { setToast } = useToast(); + const { client } = useSmartAccountClient({ type: "LightAccount" }); + const handleSuccess = () => { + setStatus(() => ({ + batch: "success", + gas: "success", + signing: "success", + })); + // Current design does not have a success toast, leaving commented to implement later. + // setToast({ + // type: "success", + // text: ( + // <> + // + // {`You've collected your NFT!`} + // + // + // {`You've successfully collected your NFT! Refresh to mint + // again.`} + // + // + // ), + // open: true, + // }); + }; + + const handleError = (error: Error) => { + console.error(error); + setStatus(initialValuePropState); + setNftTransfered(false); + setToast({ + type: "error", + text: "There was a problem with that action", + open: true, + }); + }; + + const { data: uri } = useQuery({ + queryKey: ["contractURI", nftContractAddress], + queryFn: async () => { + const uri = await client?.readContract({ + address: nftContractAddress, + abi: AccountKitNftMinterABI, + functionName: "baseURI", + }); + return uri; + }, + enabled: !!client && !!client?.readContract, + }); + const { sendUserOperation } = useSendUserOperation({ + client, + waitForTxn: true, + onError: handleError, + onSuccess: handleSuccess, + onMutate: () => { + setTimeout(() => { + setStatus((prev) => ({ ...prev, signing: "success" })); + }, 500); + setTimeout(() => { + setStatus((prev) => ({ ...prev, gas: "success" })); + }, 750); + }, + }); + + const handleCollectNFT = useCallback(async () => { + if (!client) { + console.error("no client"); + return; + } + setNftTransfered(true); + + setStatus({ + signing: "loading", + gas: "loading", + batch: "loading", + }); + sendUserOperation({ + uo: { + target: nftContractAddress, + data: encodeFunctionData({ + abi: AccountKitNftMinterABI, + functionName: "mintTo", + args: [client.getAddress()], + }), + }, + }); + }, [client, sendUserOperation]); + + return { + isLoading, + status, + nftTransfered, + handleCollectNFT, + uri, + }; +}; diff --git a/examples/ui-demo/src/components/shared/7702/useTransaction.ts b/examples/ui-demo/src/components/shared/7702/useTransaction.ts new file mode 100644 index 0000000000..0fee804792 --- /dev/null +++ b/examples/ui-demo/src/components/shared/7702/useTransaction.ts @@ -0,0 +1,112 @@ +import { useState } from "react"; +import { useSigner } from "@account-kit/react"; + +import { createPublicClient } from "viem"; +import { odyssey, splitOdysseyTransport } from "./transportSetup"; +import { + createBundlerClientFromExisting, + LocalAccountSigner, +} from "@aa-sdk/core"; +import { privateKeyToAccount } from "viem/accounts"; +import { send7702UO } from "./demoSend7702UO"; + +export type TransactionStages = "initial" | "initiating" | "next" | "complete"; +export type TransactionType = { + state: TransactionStages; + description: string; + externalLink: string; +}; + +const initialState: TransactionType[] = [ + { + state: "initial", + description: "Bought 1 ETH for 4,000 USDC", + externalLink: "www.alchemy.com", + }, + { + state: "initial", + description: "Bought 1 ETH for 3,500 USDC", + externalLink: "www.alchemy.com", + }, + { + state: "initial", + description: "Bought 1 ETH for 4,200 USDC", + externalLink: "www.alchemy.com", + }, +]; + +export const useTransactions = () => { + const [transactions, setTransactions] = + useState(initialState); + + const [isLoading, setIsLoading] = useState(false); + + const signer = useSigner(); + + const handleTransaction = async (transactionIndex: number) => { + setTransactions((prev) => { + const newState = [...prev]; + newState[transactionIndex].state = "initiating"; + if (transactionIndex + 1 < newState.length) { + newState[transactionIndex + 1].state = "next"; + } + return newState; + }); + await new Promise((resolve) => setTimeout(resolve, 3000)); + setTransactions((prev) => { + const newState = [...prev]; + newState[transactionIndex].state = "complete"; + return newState; + }); + }; + // Mock method to fire transactions for 7702 + const handleTransactions = async () => { + console.log({ initialState }); + // initial state is mutated + setIsLoading(true); + // setTransactions([ + // { + // state: "initial", + // description: "Bought 1 ETH for 4,000 USDC", + // externalLink: "www.alchemy.com", + // }, + // { + // state: "initial", + // description: "Bought 1 ETH for 3,500 USDC", + // externalLink: "www.alchemy.com", + // }, + // { + // state: "initial", + // description: "Bought 1 ETH for 4,200 USDC", + // externalLink: "www.alchemy.com", + // }, + // ]); + // for (let i = 0; i < transactions.length; i++) { + // await handleTransaction(i); + // } + + const publicClient = createPublicClient({ + chain: odyssey, + transport: splitOdysseyTransport, + }); + const bundlerClient = createBundlerClientFromExisting(publicClient); + + if (!signer) { + console.error("No signer found"); + + setIsLoading(false); + + return; + } + + send7702UO(bundlerClient, splitOdysseyTransport, signer); + + setIsLoading(false); + }; + + return { + transactions, + handleTransactions, + isLoading, + }; +}; diff --git a/examples/ui-demo/src/components/shared/WalletTypeSwitch.tsx b/examples/ui-demo/src/components/shared/WalletTypeSwitch.tsx new file mode 100644 index 0000000000..9b43192654 --- /dev/null +++ b/examples/ui-demo/src/components/shared/WalletTypeSwitch.tsx @@ -0,0 +1,53 @@ +"use client"; + +import { Root, Thumb } from "@radix-ui/react-switch"; +import { forwardRef, ElementRef, ComponentPropsWithoutRef } from "react"; + +import { cn } from "@/lib/utils"; + +const selectedStyles = "text-[#475569]"; +const unselectedStyles = "text-[#020617]"; + +const WalletTypeSwitch = forwardRef< + ElementRef, + ComponentPropsWithoutRef +>(({ className, checked, ...props }, ref) => ( + + +
+
+

+ Smart account +

+
+
+

+ Hybrid account (7702) +

+
+
+
+)); +WalletTypeSwitch.displayName = Root.displayName; + +export { WalletTypeSwitch }; diff --git a/examples/ui-demo/src/components/shared/user-connection-avatar/UserConnectionDetails.tsx b/examples/ui-demo/src/components/shared/user-connection-avatar/UserConnectionDetails.tsx index 4384f19854..255161a128 100644 --- a/examples/ui-demo/src/components/shared/user-connection-avatar/UserConnectionDetails.tsx +++ b/examples/ui-demo/src/components/shared/user-connection-avatar/UserConnectionDetails.tsx @@ -1,3 +1,4 @@ +import { WalletTypes } from "@/app/config"; import { ExternalLinkIcon } from "@/components/icons/external-link"; import { LogoutIcon } from "@/components/icons/logout"; import { DeploymentStatusIndicator } from "@/components/shared/DeploymentStatusIndicator"; @@ -15,8 +16,12 @@ export function UserConnectionDetails({ const user = useUser(); const signer = useSigner(); const { logout } = useLogout(); - const { theme, primaryColor } = useConfigStore( - ({ ui: { theme, primaryColor } }) => ({ theme, primaryColor }) + const { theme, primaryColor, walletType } = useConfigStore( + ({ ui: { theme, primaryColor }, walletType }) => ({ + theme, + primaryColor, + walletType, + }) ); const scaAccount = useAccount({ type: "LightAccount" }); @@ -69,40 +74,60 @@ export function UserConnectionDetails({ {/* Smart Account */}
- Smart account + {walletType === WalletTypes.smart ? "Smart account" : "Address"}
- {/* Status */} -
- Status -
- - - {deploymentStatus ? "Deployed" : "Not deployed"} - -
-
- {/* Signer */} -
- - - Signer - - + + ) : ( +
+ + Delegated to + +
+ + + None + +
+
+ )} {/* Logout */} diff --git a/examples/ui-demo/src/state/store.tsx b/examples/ui-demo/src/state/store.tsx index 6e588ed3cc..e99db24681 100644 --- a/examples/ui-demo/src/state/store.tsx +++ b/examples/ui-demo/src/state/store.tsx @@ -1,4 +1,4 @@ -import { Config, DEFAULT_CONFIG } from "@/app/config"; +import { Config, DEFAULT_CONFIG, WalletTypes } from "@/app/config"; import { getSectionsForConfig } from "@/app/sections"; import { AuthCardHeader } from "@/components/shared/AuthCardHeader"; import { cookieStorage, parseCookie } from "@account-kit/core"; @@ -49,6 +49,7 @@ export type DemoState = Config & { ) => void; setTheme: (theme: Config["ui"]["theme"]) => void; setSupportUrl: (url: string) => void; + setWalletType: (walletType: WalletTypes) => void; }; export const createDemoStore = (initialConfig: Config = DEFAULT_CONFIG) => { @@ -68,6 +69,7 @@ export const createDemoStore = (initialConfig: Config = DEFAULT_CONFIG) => { setTheme, setNftTransferred, nftTransferred, + setWalletType, ...config }) => config, skipHydration: true, @@ -141,6 +143,11 @@ function createInitialState( }, })); }, + setWalletType: (walletType: WalletTypes) => { + set(() => ({ + walletType, + })); + }, }); } diff --git a/examples/ui-demo/tailwind.config.ts b/examples/ui-demo/tailwind.config.ts index c69cbb7552..289f5a047b 100644 --- a/examples/ui-demo/tailwind.config.ts +++ b/examples/ui-demo/tailwind.config.ts @@ -104,6 +104,10 @@ const config = { backgroundImage: { "bg-main": "url('/images/bg-main.webp')", }, + boxShadow: { + smallCard: + "0px 50px 50px 0px rgba(0, 0, 0, 0.09), 0px 12px 27px 0px rgba(0, 0, 0, 0.10)", + }, }, }, plugins: [require("tailwindcss-animate"), require("tailwind-scrollbar")], diff --git a/package.json b/package.json index 21d4b67145..91dc4126c0 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ }, "resolutions": { "wagmi": "2.12.7", - "viem": "2.20.0" + "viem": "2.22.6" }, "scripts": { "generate": "turbo run generate", @@ -83,7 +83,7 @@ "prool": "^0.0.15", "tsx": "^4.19.2", "turbo": "^2.2.3", - "viem": "2.20.0", + "viem": "2.22.6", "vitest": "^2.0.4", "wagmi": "2.12.7", "webauthn-p256": "^0.0.10" diff --git a/site/package.json b/site/package.json index 267bfc104e..84451d3ceb 100644 --- a/site/package.json +++ b/site/package.json @@ -31,7 +31,7 @@ "react": "^18.2.0", "react-native": "0.76.5", "react-dom": "^18.2.0", - "viem": "2.20.0", + "viem": "2.22.6", "vocs": "^1.0.0-alpha.62", "wagmi": "2.12.7" } diff --git a/site/pages/reference/aa-sdk/core/classes/LocalAccountSigner/signAuthorization.mdx b/site/pages/reference/aa-sdk/core/classes/LocalAccountSigner/signAuthorization.mdx new file mode 100644 index 0000000000..d3564d7067 --- /dev/null +++ b/site/pages/reference/aa-sdk/core/classes/LocalAccountSigner/signAuthorization.mdx @@ -0,0 +1,43 @@ +--- +# This file is autogenerated + +title: signAuthorization +description: Overview of the signAuthorization method +--- + +# signAuthorization + +Signs an unsigned authorization using the provided private key account. + +## Import + +```ts +import { LocalAccountSigner } from "@aa-sdk/core"; +``` + +## Usage + +```ts +import { LocalAccountSigner } from "@aa-sdk/core"; +import { generatePrivateKey } from "viem"; + +const signer = LocalAccountSigner.mnemonicToAccountSigner(generatePrivateKey()); +const signedAuthorization = await signer.signAuthorization({ + contractAddress: "0x1234123412341234123412341234123412341234", + chainId: 1, + nonce: 3, +}); +``` + +## Parameters + +### unsignedAuthorization + +`Authorization` + +- The unsigned authorization to be signed. + + ## Returns + + `Promise>` + A promise that resolves to the signed authorization. diff --git a/site/pages/reference/aa-sdk/core/functions/default7702GasEstimator.mdx b/site/pages/reference/aa-sdk/core/functions/default7702GasEstimator.mdx new file mode 100644 index 0000000000..d757a14b6d --- /dev/null +++ b/site/pages/reference/aa-sdk/core/functions/default7702GasEstimator.mdx @@ -0,0 +1,28 @@ +--- +# This file is autogenerated +title: default7702GasEstimator +description: Overview of the default7702GasEstimator method +--- + +# default7702GasEstimator + +A middleware function to estimate the gas usage of a user operation with an optional custom gas estimator. +This function is only compatible with accounts using EntryPoint v0.7.0. + +## Import + +```ts +import { default7702GasEstimator } from "@aa-sdk/core"; +``` + +## Parameters + +### gasEstimator + +`ClientMiddlewareFn` +An optional custom gas estimator function + +## Returns + +`Function` +A function that takes user operation structure and parameters, estimates gas usage, and returns the estimated user operation diff --git a/site/pages/reference/aa-sdk/core/functions/default7702UserOpSigner.mdx b/site/pages/reference/aa-sdk/core/functions/default7702UserOpSigner.mdx new file mode 100644 index 0000000000..67653b606d --- /dev/null +++ b/site/pages/reference/aa-sdk/core/functions/default7702UserOpSigner.mdx @@ -0,0 +1,28 @@ +--- +# This file is autogenerated +title: default7702UserOpSigner +description: Overview of the default7702UserOpSigner method +--- + +# default7702UserOpSigner + +Provides a default middleware function for signing user operations with a client account when using ERC-7702 to upgrade local accounts to smart accounts. +If the SmartAccount doesn't support `signAuthorization`, then this just runs the provided `signUserOperation` middleware + +## Import + +```ts +import { default7702UserOpSigner } from "@aa-sdk/core"; +``` + +## Parameters + +### userOpSigner + +`ClientMiddlewareFn` +Optional user operation signer function + +## Returns + +`Function` +An async function that processes the user operation and returns the authorized operation with an authorization tuple if necessary diff --git a/site/pages/reference/account-kit/signer/classes/BaseAlchemySigner/signAuthorization.mdx b/site/pages/reference/account-kit/signer/classes/BaseAlchemySigner/signAuthorization.mdx new file mode 100644 index 0000000000..2547cfa279 --- /dev/null +++ b/site/pages/reference/account-kit/signer/classes/BaseAlchemySigner/signAuthorization.mdx @@ -0,0 +1,51 @@ +--- +# This file is autogenerated + +title: signAuthorization +description: Overview of the signAuthorization method +--- + +# signAuthorization + +Signs an EIP-7702 Authorization and then returns the authorization with the signature. + +## Import + +```ts +import { BaseAlchemySigner } from "@account-kit/signer"; +``` + +## Usage + +```ts +import { AlchemyWebSigner } from "@account-kit/signer"; + +const signer = new AlchemyWebSigner({ + client: { + connection: { + rpcUrl: "/api/rpc", + }, + iframeConfig: { + iframeContainerId: "alchemy-signer-iframe-container", + }, + }, +}); + +const tx = await signer.signAuthorization({ + contractAddress: "0x1234", + chainId: 1, + nonce: 0, +}); +``` + +## Parameters + +### unsignedAuthorization + +`Authorization` +the authorization to be signed + +## Returns + +`Promise> | undefined` +a promise that resolves to the authorization with the signature diff --git a/site/pages/reference/account-kit/smart-contracts/functions/createSMAV2Account.mdx b/site/pages/reference/account-kit/smart-contracts/functions/createSMAV2Account.mdx deleted file mode 100644 index d789f0559b..0000000000 --- a/site/pages/reference/account-kit/smart-contracts/functions/createSMAV2Account.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -# This file is autogenerated -title: createSMAV2Account -description: Overview of the createSMAV2Account method ---- - -# createSMAV2Account - -Creates an SMAV2 account using defined parameters including chain, signer, salt, factory address, and more. -Handles account initialization code, nonce generation, transaction encoding, and more to construct a modular account with optional validation hooks. - -## Import - -```ts -import { createSMAV2Account } from "@account-kit/smart-contracts"; -``` - -## Parameters - -### config - -`CreateSMAV2AccountParams` -Configuration parameters for creating an SMAV2 account. Includes chain details, signer, salt, factory address, and more. - -## Returns - -`Promise` -A promise that resolves to an `MAV2Account` providing methods for nonce retrieval, transaction execution, and more. diff --git a/site/pages/reference/account-kit/smart-contracts/functions/createSMAV2AccountClient.mdx b/site/pages/reference/account-kit/smart-contracts/functions/createSMAV2AccountClient.mdx deleted file mode 100644 index 8b7bcd96ab..0000000000 --- a/site/pages/reference/account-kit/smart-contracts/functions/createSMAV2AccountClient.mdx +++ /dev/null @@ -1,52 +0,0 @@ ---- -# This file is autogenerated - -title: createSMAV2AccountClient -description: Overview of the createSMAV2AccountClient method ---- - -# createSMAV2AccountClient - -Creates a SMAv2 account client using the provided configuration parameters. - -## Import - -```ts -import { createSMAV2AccountClient } from "@account-kit/smart-contracts"; -``` - -## Usage - -```ts -import { http } from "viem"; -import { createSMAV2AccountClient } from "@account-kit/smart-contracts"; -import { LocalAccountSigner } from "@aa-sdk/core"; -import { sepolia } from "@account-kit/infra"; - -const MNEMONIC = "..."; -const RPC_URL = "..."; - -const signer = LocalAccountSigner.mnemonicToAccountSigner(MNEMONIC); - -const chain = sepolia; - -const transport = http(RPC_URL); - -const SMAV2SignerAccountClient = await createSMAV2AccountClient({ - chain, - signer, - transport, -}); -``` - -## Parameters - -### config - -`CreateSMAV2AccountClientParams` -The configuration parameters required to create the MAv2 account client - -## Returns - -`Promise` -A promise that resolves to a `SmartAccountClient` instance diff --git a/site/pages/reference/account-kit/smart-contracts/functions/getDefaultAllowlistModuleAddress.mdx b/site/pages/reference/account-kit/smart-contracts/functions/getDefaultAllowlistModuleAddress.mdx deleted file mode 100644 index 5522e43076..0000000000 --- a/site/pages/reference/account-kit/smart-contracts/functions/getDefaultAllowlistModuleAddress.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -# This file is autogenerated -title: getDefaultAllowlistModuleAddress -description: Overview of the getDefaultAllowlistModuleAddress method ---- - -# getDefaultAllowlistModuleAddress - -Maps a given chain to a specific address of the allowlist module by its chain ID. If no direct mapping exists, it defaults to returning a specific address. - -## Import - -```ts -import { getDefaultAllowlistModuleAddress } from "@account-kit/smart-contracts"; -``` - -## Usage - -```ts -import { getDefaultAllowlistModuleAddress } from "@account-kit/smart-contracts"; -import { Chain, Address } from "viem"; - -const chain: Chain = ... -const allowlistModule: Address = getDefaultAllowlistModuleAddress(chain); -``` - -## Parameters - -### chain - -`Chain` -The chain object containing the chain ID to map - -## Returns - -`Address` -The allowlist module address associated with the specified chain ID or a default address if no specific mapping exists diff --git a/site/pages/reference/account-kit/smart-contracts/functions/getDefaultNativeTokenLimitModuleAddress.mdx b/site/pages/reference/account-kit/smart-contracts/functions/getDefaultNativeTokenLimitModuleAddress.mdx deleted file mode 100644 index 54dcc49268..0000000000 --- a/site/pages/reference/account-kit/smart-contracts/functions/getDefaultNativeTokenLimitModuleAddress.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -# This file is autogenerated -title: getDefaultNativeTokenLimitModuleAddress -description: Overview of the getDefaultNativeTokenLimitModuleAddress method ---- - -# getDefaultNativeTokenLimitModuleAddress - -Maps a given chain to a specific address of the native token limit module by its chain ID. If no direct mapping exists, it defaults to returning a specific address. - -## Import - -```ts -import { getDefaultNativeTokenLimitModuleAddress } from "@account-kit/smart-contracts"; -``` - -## Usage - -```ts -import { getDefaultNativeTokenLimitModuleAddress } from "@account-kit/smart-contracts"; -import { Chain, Address } from "viem"; - -const chain: Chain = ... -const nativeTokenLimitAddress: Address = getDefaultNativeTokenLimitModuleAddress(chain); -``` - -## Parameters - -### chain - -`Chain` -The chain object containing the chain ID to map - -## Returns - -`Address` -The native token limit module address associated with the specified chain ID or a default address if no specific mapping exists diff --git a/site/pages/reference/account-kit/smart-contracts/functions/getDefaultPaymasterGuardModuleAddress.mdx b/site/pages/reference/account-kit/smart-contracts/functions/getDefaultPaymasterGuardModuleAddress.mdx deleted file mode 100644 index 11e25ca3b0..0000000000 --- a/site/pages/reference/account-kit/smart-contracts/functions/getDefaultPaymasterGuardModuleAddress.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -# This file is autogenerated -title: getDefaultPaymasterGuardModuleAddress -description: Overview of the getDefaultPaymasterGuardModuleAddress method ---- - -# getDefaultPaymasterGuardModuleAddress - -Maps a given chain to a specific address of the paymaster guard module by its chain ID. If no direct mapping exists, it defaults to returning a specific address. - -## Import - -```ts -import { getDefaultPaymasterGuardModuleAddress } from "@account-kit/smart-contracts"; -``` - -## Usage - -```ts -import { getDefaultPaymasterGuardModuleAddress } from "@account-kit/smart-contracts"; -import { Chain, Address } from "viem"; - -const chain: Chain = ... -const paymasterGuardAddress: Address = getDefaultPaymasterGuardModuleAddress(chain); -``` - -## Parameters - -### chain - -`Chain` -The chain object containing the chain ID to map - -## Returns - -`Address` -The paymaster guard module address associated with the specified chain ID or a default address if no specific mapping exists diff --git a/site/pages/reference/account-kit/smart-contracts/functions/getDefaultSingleSignerValidationModuleAddress.mdx b/site/pages/reference/account-kit/smart-contracts/functions/getDefaultSingleSignerValidationModuleAddress.mdx deleted file mode 100644 index 04c02888cc..0000000000 --- a/site/pages/reference/account-kit/smart-contracts/functions/getDefaultSingleSignerValidationModuleAddress.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -# This file is autogenerated -title: getDefaultSingleSignerValidationModuleAddress -description: Overview of the getDefaultSingleSignerValidationModuleAddress method ---- - -# getDefaultSingleSignerValidationModuleAddress - -Maps a given chain to a specific address of the single signer validation module by its chain ID. If no direct mapping exists, it defaults to returning a specific address. - -## Import - -```ts -import { getDefaultSingleSignerValidationModuleAddress } from "@account-kit/smart-contracts"; -``` - -## Usage - -```ts -import { getDefaultSingleSignerValidationModuleAddress } from "@account-kit/smart-contracts"; -import { Chain, Address } from "viem"; - -const chain: Chain = ... -const singleSignerValidationAddress: Address = getDefaultSingleSignerValidationModuleAddress(chain); -``` - -## Parameters - -### chain - -`Chain` -The chain object containing the chain ID to map - -## Returns - -`Address` -The single signer validation module address associated with the specified chain ID or a default address if no specific mapping exists diff --git a/site/pages/reference/account-kit/smart-contracts/functions/getDefaultTimeRangeModuleAddress.mdx b/site/pages/reference/account-kit/smart-contracts/functions/getDefaultTimeRangeModuleAddress.mdx deleted file mode 100644 index 3de832b874..0000000000 --- a/site/pages/reference/account-kit/smart-contracts/functions/getDefaultTimeRangeModuleAddress.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -# This file is autogenerated -title: getDefaultTimeRangeModuleAddress -description: Overview of the getDefaultTimeRangeModuleAddress method ---- - -# getDefaultTimeRangeModuleAddress - -Maps a given chain to a specific address of the time range module by its chain ID. If no direct mapping exists, it defaults to returning a specific address. - -## Import - -```ts -import { getDefaultTimeRangeModuleAddress } from "@account-kit/smart-contracts"; -``` - -## Usage - -```ts -import { getDefaultTimeRangeModuleAddress } from "@account-kit/smart-contracts"; -import { Chain, Address } from "viem"; - -const chain: Chain = ... -const timeRangeModuleAddress: Address = getDefaultTimeRangeModuleAddress(chain); -``` - -## Parameters - -### chain - -`Chain` -The chain object containing the chain ID to map - -## Returns - -`Address` -The time range module address associated with the specified chain ID or a default address if no specific mapping exists diff --git a/site/pages/reference/account-kit/smart-contracts/functions/getDefaultWebauthnValidationModuleAddress.mdx b/site/pages/reference/account-kit/smart-contracts/functions/getDefaultWebauthnValidationModuleAddress.mdx deleted file mode 100644 index fd27c9dac5..0000000000 --- a/site/pages/reference/account-kit/smart-contracts/functions/getDefaultWebauthnValidationModuleAddress.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -# This file is autogenerated -title: getDefaultWebauthnValidationModuleAddress -description: Overview of the getDefaultWebauthnValidationModuleAddress method ---- - -# getDefaultWebauthnValidationModuleAddress - -Maps a given chain to a specific address of the webauthn validation module by its chain ID. If no direct mapping exists, it defaults to returning a specific address. - -## Import - -```ts -import { getDefaultWebauthnValidationModuleAddress } from "@account-kit/smart-contracts"; -``` - -## Usage - -```ts -import { getDefaultWebauthnValidationModuleAddress } from "@account-kit/smart-contracts"; -import { Chain, Address } from "viem"; - -const chain: Chain = ... -const webauthnValidationAddress: Address = getDefaultWebauthnValidationModuleAddress(chain); -``` - -## Parameters - -### chain - -`Chain` -The chain object containing the chain ID to map - -## Returns - -`Address` -The webauthn validation module address associated with the specified chain ID or a default address if no specific mapping exists diff --git a/site/pages/reference/account-kit/smart-contracts/functions/installValidationActions.mdx b/site/pages/reference/account-kit/smart-contracts/functions/installValidationActions.mdx deleted file mode 100644 index 602162dacc..0000000000 --- a/site/pages/reference/account-kit/smart-contracts/functions/installValidationActions.mdx +++ /dev/null @@ -1,69 +0,0 @@ ---- -# This file is autogenerated - -title: installValidationActions -description: Overview of the installValidationActions method ---- - -# installValidationActions - -Provides validation installation and uninstallation functionalities for a MA v2 client, ensuring compatibility with `SmartAccountClient`. - -## Import - -```ts -import { installValidationActions } from "@account-kit/smart-contracts"; -``` - -## Usage - -```ts -import { createSMAV2AccountClient, installValidationActions, getDefaultSingleSignerValidationModuleAddress, SingleSignerValidationModule } from "@account-kit/smart-contracts"; -import { Address } from "viem"; - -const client = (await createSMAV2AccountClient({ ... })).extend(installValidationActions); -const sessionKeyAddress: Address = "0x1234"; -const sessionKeyEntityId: number = 1; - -await client.installValidation({ -validationConfig: { -moduleAddress: getDefaultSingleSignerValidationModuleAddress( - client.chain -), -entityId: sessionKeyEntityId, -isGlobal: true, -isSignatureValidation: false, -isUserOpValidation: true, -}, -selectors: [], -installData: SingleSignerValidationModule.encodeOnInstallData({ -entityId: sessionKeyEntityId, -signer: sessionKeyAddress, -}), -hooks: [], -}); - -await client.uninstallValidation({ -moduleAddress: sessionKeyAddress, -entityId: sessionKeyEntityId, -uninstallData: SingleSignerValidationModule.encodeOnUninstallData({ -entityId: sessionKeyEntityId, -}), -hookUninstallDatas: [], -}); - -``` - -## Parameters - -### client - -`object` - -- The client instance which provides account and sendUserOperation functionality. - - ## Returns - - `object` - -- An object containing two methods, `installValidation` and `uninstallValidation`. diff --git a/site/pages/reference/account-kit/smart-contracts/functions/nativeSMASigner.mdx b/site/pages/reference/account-kit/smart-contracts/functions/nativeSMASigner.mdx deleted file mode 100644 index 0052b9b056..0000000000 --- a/site/pages/reference/account-kit/smart-contracts/functions/nativeSMASigner.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -# This file is autogenerated -title: nativeSMASigner -description: Overview of the nativeSMASigner method ---- - -# nativeSMASigner - -Creates an object with methods for generating a dummy signature, signing user operation hashes, signing messages, and signing typed data. - -## Import - -```ts -import { nativeSMASigner } from "@account-kit/smart-contracts"; -``` - -## Usage - -```ts -import { nativeSMASigner } from "@account-kit/smart-contracts"; - -import { LocalAccountSigner } from "@aa-sdk/core"; - -const MNEMONIC = "...": - -const account = createSMAV2Account({ config }); - -const signer = LocalAccountSigner.mnemonicToAccountSigner(MNEMONIC); - -const messageSigner = nativeSMASigner(signer, chain, account.address); -``` - -## Parameters - -### signer - -`SmartAccountSigner` -Signer to use for signing operations - -### chain - -`Chain` -Chain object for the signer - -### accountAddress - -`Address` -address of the smart account using this signer - -## Returns - -`object` -an object with methods for signing operations and managing signatures diff --git a/site/pages/reference/account-kit/smart-contracts/functions/serializeHookConfig.mdx b/site/pages/reference/account-kit/smart-contracts/functions/serializeHookConfig.mdx deleted file mode 100644 index 94b6f1f3b1..0000000000 --- a/site/pages/reference/account-kit/smart-contracts/functions/serializeHookConfig.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -# This file is autogenerated - -title: serializeHookConfig -description: Overview of the serializeHookConfig method ---- - -# serializeHookConfig - -Serializes a `HookConfig` object into a `Hex` format by encoding the hook type, presence of post/pre hooks, address, and entity ID. - -## Import - -```ts -import { serializeHookConfig } from "@account-kit/smart-contracts"; -``` - -## Usage - -```ts -import { type HookType, serializeHookConfig } from "@account-kit/smart-contracts"; -import { Address } from "viem"; - -const moduleAddress: Address = "0x1234"; -const entityId: number = 1234; -const hookType: HookType = HookType.Validation; -const hasPostHooks: boolean = false; -const hasPreHooks: boolean = true; - -const hookConfigHex = serializeHookConfig({ -moduleAddress, -entityId -hookType, -hasPostHooks, -hasPreHooks -}); -``` - -## Parameters - -### config - -`HookConfig` -The hook configuration containing address, entity ID, hook type, and post/pre hook indicators - -## Returns - -`Hex` -The serialized hook configuration in hexadecimal format diff --git a/site/pages/reference/account-kit/smart-contracts/functions/serializeModuleEntity.mdx b/site/pages/reference/account-kit/smart-contracts/functions/serializeModuleEntity.mdx deleted file mode 100644 index a95495eaa9..0000000000 --- a/site/pages/reference/account-kit/smart-contracts/functions/serializeModuleEntity.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -# This file is autogenerated - -title: serializeModuleEntity -description: Overview of the serializeModuleEntity method ---- - -# serializeModuleEntity - -Serializes a module entity into a hexadecimal format by concatenating the module address and entity ID. - -## Import - -```ts -import { serializeModuleEntity } from "@account-kit/smart-contracts"; -``` - -## Usage - -```ts -import { serializeModuleEntity } from "@account-kit/smart-contracts"; -import { Address } from "viem"; - -const moduleAddress: Address = "0x1234"; -const entityId: number = 1234; - -const moduleEntityHex = serializeModuleEntity({ - moduleAddress, - entityId, -}); -``` - -## Parameters - -### config - -`ModuleEntity` -The module entity configuration containing the module address and entity ID - -## Returns - -`Hex` -A hexadecimal string representation of the serialized module entity diff --git a/site/pages/reference/account-kit/smart-contracts/functions/serializeValidationConfig.mdx b/site/pages/reference/account-kit/smart-contracts/functions/serializeValidationConfig.mdx deleted file mode 100644 index f66a26e095..0000000000 --- a/site/pages/reference/account-kit/smart-contracts/functions/serializeValidationConfig.mdx +++ /dev/null @@ -1,49 +0,0 @@ ---- -# This file is autogenerated - -title: serializeValidationConfig -description: Overview of the serializeValidationConfig method ---- - -# serializeValidationConfig - -Serializes a validation configuration into a hexadecimal string representation. This involves converting boolean flags into bitwise representation and combining them with serialized module entity data. - -## Import - -```ts -import { serializeValidationConfig } from "@account-kit/smart-contracts"; -``` - -## Usage - -```ts -import { serializeValidationConfig } from "@account-kit/smart-contracts"; -import { Address } from "viem"; - -const moduleAddress: Address = "0x1234"; -const entityId: number = 1234; -const isGlobal: boolean = true; -const isSignatureValidation: boolean = false; -const isUserOpValidation: boolean = true; - -const validationConfigHex = serializeValidationConfig({ -moduleAddress, -entityId -isGlobal, -isSignatureValidation, -isUserOpValidation -}); -``` - -## Parameters - -### config - -`ValidationConfig` -The validation configuration object containing details to serialize - -## Returns - -`Hex` -A hexadecimal string representing the serialized configuration diff --git a/yarn.lock b/yarn.lock index 00390a71a7..ee359b75fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17,10 +17,10 @@ resolved "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz" integrity sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ== -"@adraffy/ens-normalize@1.10.0": - version "1.10.0" - resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz" - integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== +"@adraffy/ens-normalize@^1.10.1": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz#42cc67c5baa407ac25059fcd7d405cc5ecdb0c33" + integrity sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg== "@alloc/quick-lru@^5.2.0": version "5.2.0" @@ -4748,12 +4748,12 @@ dependencies: "@noble/hashes" "1.3.1" -"@noble/curves@1.4.0": - version "1.4.0" - resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz" - integrity sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg== +"@noble/curves@1.7.0", "@noble/curves@~1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.7.0.tgz#0512360622439256df892f21d25b388f52505e45" + integrity sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw== dependencies: - "@noble/hashes" "1.4.0" + "@noble/hashes" "1.6.0" "@noble/curves@^1.3.0": version "1.3.0" @@ -4769,12 +4769,12 @@ dependencies: "@noble/hashes" "1.4.0" -"@noble/curves@~1.4.0": - version "1.4.2" - resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz" - integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== +"@noble/curves@^1.6.0", "@noble/curves@~1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.0.tgz#fe035a23959e6aeadf695851b51a87465b5ba8f7" + integrity sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ== dependencies: - "@noble/hashes" "1.4.0" + "@noble/hashes" "1.7.0" "@noble/hashes@1.3.1": version "1.3.1" @@ -4786,11 +4786,26 @@ resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz" integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== -"@noble/hashes@1.4.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.3.2", "@noble/hashes@^1.4.0", "@noble/hashes@~1.4.0": +"@noble/hashes@1.4.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.3.2", "@noble/hashes@^1.4.0": version "1.4.0" resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz" integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== +"@noble/hashes@1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.0.tgz#d4bfb516ad6e7b5111c216a5cc7075f4cf19e6c5" + integrity sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ== + +"@noble/hashes@1.6.1", "@noble/hashes@~1.6.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5" + integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w== + +"@noble/hashes@1.7.0", "@noble/hashes@~1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.0.tgz#5d9e33af2c7d04fee35de1519b80c958b2e35e39" + integrity sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w== + "@noble/hashes@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0" @@ -6768,10 +6783,10 @@ resolved "https://registry.npmjs.org/@scure/base/-/base-1.1.4.tgz" integrity sha512-wznebWtt+ejH8el87yuD4i9xLSbYZXf1Pe4DY0o/zq/eg5I0VQVXVbFs6XIM0pNVCJ/uE3t5wI9kh90mdLUxtw== -"@scure/base@~1.1.6": - version "1.1.7" - resolved "https://registry.npmjs.org/@scure/base/-/base-1.1.7.tgz" - integrity sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g== +"@scure/base@~1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.1.tgz#dd0b2a533063ca612c17aa9ad26424a2ff5aa865" + integrity sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ== "@scure/bip32@1.3.1": version "1.3.1" @@ -6782,14 +6797,23 @@ "@noble/hashes" "~1.3.1" "@scure/base" "~1.1.0" -"@scure/bip32@1.4.0": - version "1.4.0" - resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz" - integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== +"@scure/bip32@1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.0.tgz#6dbc6b4af7c9101b351f41231a879d8da47e0891" + integrity sha512-82q1QfklrUUdXJzjuRU7iG7D7XiFx5PHYVS0+oeNKhyDLT7WPqs6pBcM2W5ZdwOwKCwoE1Vy1se+DHjcXwCYnA== + dependencies: + "@noble/curves" "~1.7.0" + "@noble/hashes" "~1.6.0" + "@scure/base" "~1.2.1" + +"@scure/bip32@^1.5.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.1.tgz#848eca1bc96f6b5ce6aa750798853fb142dace05" + integrity sha512-jSO+5Ud1E588Y+LFo8TaB8JVPNAZw/lGGao+1SepHDeTs2dFLurdNIAgUuDlwezqEjRjElkCJajVrtrZaBxvaQ== dependencies: - "@noble/curves" "~1.4.0" - "@noble/hashes" "~1.4.0" - "@scure/base" "~1.1.6" + "@noble/curves" "~1.8.0" + "@noble/hashes" "~1.7.0" + "@scure/base" "~1.2.1" "@scure/bip39@1.2.1": version "1.2.1" @@ -6799,13 +6823,21 @@ "@noble/hashes" "~1.3.0" "@scure/base" "~1.1.0" -"@scure/bip39@1.3.0": - version "1.3.0" - resolved "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz" - integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== +"@scure/bip39@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.0.tgz#c8f9533dbd787641b047984356531d84485f19be" + integrity sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A== + dependencies: + "@noble/hashes" "~1.6.0" + "@scure/base" "~1.2.1" + +"@scure/bip39@^1.4.0": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.1.tgz#a056868d672c7203a6035c808893742a79e151f6" + integrity sha512-GnlufVSP9UdAo/H2Patfv22VTtpNTyfi+I3qCKpvuB5l1KWzEYx+l2TNpBy9Ksh4xTs3Rn06tBlpWCi/1Vz8gw== dependencies: - "@noble/hashes" "~1.4.0" - "@scure/base" "~1.1.6" + "@noble/hashes" "~1.7.0" + "@scure/base" "~1.2.1" "@sec-ant/readable-stream@^0.4.1": version "0.4.1" @@ -9976,16 +10008,21 @@ abbrev@^2.0.0: resolved "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz" integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ== -abitype@1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/abitype/-/abitype-1.0.5.tgz" - integrity sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw== +abitype@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.7.tgz#876a0005d211e1c9132825d45bcee7b46416b284" + integrity sha512-ZfYYSktDQUwc2eduYu8C4wOs+RDPmnRYMh7zNfzeMtGGgb0U+6tLGjixUic6mXf5xKKCcgT5Qp6cv39tOARVFw== abitype@^0.8.3: version "0.8.11" resolved "https://registry.npmjs.org/abitype/-/abitype-0.8.11.tgz" integrity sha512-bM4v2dKvX08sZ9IU38IN5BKmN+ZkOSd2oI4a9f0ejHYZQYV6cDr7j+d95ga0z2XHG36Y4jzoG5Z7qDqxp7fi/A== +abitype@^1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.8.tgz#3554f28b2e9d6e9f35eb59878193eabd1b9f46ba" + integrity sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg== + abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz" @@ -18032,10 +18069,10 @@ isobject@^3.0.1: resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -isows@1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/isows/-/isows-1.0.4.tgz" - integrity sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ== +isows@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.6.tgz#0da29d706fa51551c663c627ace42769850f86e7" + integrity sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw== issue-parser@6.0.0: version "6.0.0" @@ -22810,6 +22847,19 @@ outvariant@^1.4.0, outvariant@^1.4.2, outvariant@^1.4.3: resolved "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz" integrity sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA== +ox@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/ox/-/ox-0.6.0.tgz#ba8f89d68b5e8afe717c8a947ffacc0669ea155d" + integrity sha512-blUzTLidvUlshv0O02CnLFqBLidNzPoAZdIth894avUAotTuWziznv6IENv5idRuOSSP3dH8WzcYw84zVdu0Aw== + dependencies: + "@adraffy/ens-normalize" "^1.10.1" + "@noble/curves" "^1.6.0" + "@noble/hashes" "^1.5.0" + "@scure/bip32" "^1.5.0" + "@scure/bip39" "^1.4.0" + abitype "^1.0.6" + eventemitter3 "5.0.1" + p-cancelable@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" @@ -28383,20 +28433,20 @@ vfile@^6.0.0, vfile@^6.0.1: unist-util-stringify-position "^4.0.0" vfile-message "^4.0.0" -viem@2.20.0, viem@^2.1.1, viem@^2.20.0, viem@^2.21.40, viem@^2.21.41: - version "2.20.0" - resolved "https://registry.npmjs.org/viem/-/viem-2.20.0.tgz" - integrity sha512-cM4vs81HnSNbfceI1MLkx4pCVzbVjl9xiNSv5SCutYjUyFFOVSPDlEyhpg2iHinxx1NM4Qne3END5eLT8rvUdg== - dependencies: - "@adraffy/ens-normalize" "1.10.0" - "@noble/curves" "1.4.0" - "@noble/hashes" "1.4.0" - "@scure/bip32" "1.4.0" - "@scure/bip39" "1.3.0" - abitype "1.0.5" - isows "1.0.4" - webauthn-p256 "0.0.5" - ws "8.17.1" +viem@2.22.6, viem@^2.1.1, viem@^2.21.40, viem@^2.21.41, viem@^2.22.6: + version "2.22.6" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.22.6.tgz#724c66caed2c8bfd73748f099131e60d392e26ef" + integrity sha512-wbru5XP0Aa2QskBrZsv7VOriqRnAKn0tahs957xRPOM00ABN4AGAY9xM16UvIq+giRJU6oahXDhPrR1QaYymoA== + dependencies: + "@noble/curves" "1.7.0" + "@noble/hashes" "1.6.1" + "@scure/bip32" "1.6.0" + "@scure/bip39" "1.5.0" + abitype "1.0.7" + isows "1.0.6" + ox "0.6.0" + webauthn-p256 "0.0.10" + ws "8.18.0" vite-node@2.0.4: version "2.0.4" @@ -28636,17 +28686,9 @@ web-vitals@0.2.4: resolved "https://registry.npmjs.org/web-vitals/-/web-vitals-0.2.4.tgz" integrity sha512-6BjspCO9VriYy12z356nL6JBS0GYeEcA457YyRzD+dD6XYCQ75NKhcOHUMHentOE7OcVCIXXDvOm0jKFfQG2Gg== -webauthn-p256@0.0.5: - version "0.0.5" - resolved "https://registry.npmjs.org/webauthn-p256/-/webauthn-p256-0.0.5.tgz" - integrity sha512-drMGNWKdaixZNobeORVIqq7k5DsRC9FnG201K2QjeOoQLmtSDaSsVZdkg6n5jUALJKcAG++zBPJXmv6hy0nWFg== - dependencies: - "@noble/curves" "^1.4.0" - "@noble/hashes" "^1.4.0" - -webauthn-p256@^0.0.10: +webauthn-p256@0.0.10, webauthn-p256@^0.0.10: version "0.0.10" - resolved "https://registry.npmjs.org/webauthn-p256/-/webauthn-p256-0.0.10.tgz" + resolved "https://registry.yarnpkg.com/webauthn-p256/-/webauthn-p256-0.0.10.tgz#877e75abe8348d3e14485932968edf3325fd2fdd" integrity sha512-EeYD+gmIT80YkSIDb2iWq0lq2zbHo1CxHlQTeJ+KkCILWpVy3zASH3ByD4bopzfk0uCwXxLqKGLqp2W4O28VFA== dependencies: "@noble/curves" "^1.4.0" @@ -28974,10 +29016,10 @@ ws@7.4.6: resolved "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== -ws@8.17.1: - version "8.17.1" - resolved "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz" - integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== +ws@8.18.0, ws@^8.12.1, ws@^8.18.0, ws@^8.2.3: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== ws@^6.2.3: version "6.2.3" @@ -28996,11 +29038,6 @@ ws@^7.5.1: resolved "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== -ws@^8.12.1, ws@^8.18.0, ws@^8.2.3: - version "8.18.0" - resolved "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz" - integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== - ws@~8.11.0: version "8.11.0" resolved "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz"