From 7de81154c3aac4ca2ecce401f9182b6de0acc33a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Coffee=20=E2=98=95=EF=B8=8F?= Date: Sun, 26 Jan 2025 17:48:54 -0500 Subject: [PATCH] feat: update signing to support non-executing sign thru privy-cross-app (#206) * feat: update signing to support non-executing sign thru privy-cross-app * update typed data sign flow to pull custom signature from RLP encoded sig * remove unused imports * updates for non-executing tx via sign typed data * update test * changeset --- .changeset/gorgeous-fireants-vanish.md | 7 ++ .../src/actions/sendPrivyTransaction.ts | 22 ++++++ .../agw-client/src/actions/signTransaction.ts | 6 ++ .../agw-client/src/actions/signTypedData.ts | 68 +++++++++++-------- packages/agw-client/src/utils.ts | 31 +++++---- packages/agw-client/src/walletActions.ts | 4 ++ .../test/src/actions/signTypedData.test.ts | 6 +- .../agw-client/test/src/walletActions.test.ts | 4 ++ packages/agw-react/package.json | 2 +- pnpm-lock.yaml | 36 +++++----- 10 files changed, 125 insertions(+), 61 deletions(-) create mode 100644 .changeset/gorgeous-fireants-vanish.md diff --git a/.changeset/gorgeous-fireants-vanish.md b/.changeset/gorgeous-fireants-vanish.md new file mode 100644 index 0000000..efe3b17 --- /dev/null +++ b/.changeset/gorgeous-fireants-vanish.md @@ -0,0 +1,7 @@ +--- +'@abstract-foundation/agw-client': minor +'@abstract-foundation/agw-react': minor +'@abstract-foundation/web3-react-agw': minor +--- + +Add non executing transaction signing diff --git a/packages/agw-client/src/actions/sendPrivyTransaction.ts b/packages/agw-client/src/actions/sendPrivyTransaction.ts index 06f8191..cefcd14 100644 --- a/packages/agw-client/src/actions/sendPrivyTransaction.ts +++ b/packages/agw-client/src/actions/sendPrivyTransaction.ts @@ -11,6 +11,7 @@ import { import { type ChainEIP712, type SendEip712TransactionParameters, + type SignEip712TransactionParameters, type SignEip712TransactionReturnType, } from 'viem/zksync'; @@ -71,3 +72,24 @@ export async function sendPrivySignTypedData( )) as Hex; return result; } + +export async function signPrivyTransaction< + chain extends ChainEIP712 | undefined = ChainEIP712 | undefined, + account extends Account | undefined = Account | undefined, + chainOverride extends ChainEIP712 | undefined = ChainEIP712 | undefined, +>( + client: Client, + parameters: SignEip712TransactionParameters, +): Promise { + const { chain: _chain, account: _account, ...request } = parameters; + + const result = (await client.request( + { + method: 'privy_signSmartWalletTx', + params: [replaceBigInts(request, toHex)], + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any, + { retryCount: 0 }, + )) as SignEip712TransactionReturnType; + return result; +} diff --git a/packages/agw-client/src/actions/signTransaction.ts b/packages/agw-client/src/actions/signTransaction.ts index 0cd4eae..726a6d5 100644 --- a/packages/agw-client/src/actions/signTransaction.ts +++ b/packages/agw-client/src/actions/signTransaction.ts @@ -27,6 +27,7 @@ import { import { AccountNotFoundError } from '../errors/account.js'; import { VALID_CHAINS } from '../utils.js'; import { transformHexValues } from '../utils.js'; +import { signPrivyTransaction } from './sendPrivyTransaction.js'; export interface CustomPaymasterParameters { nonce: number; @@ -61,9 +62,14 @@ export async function signTransaction< useSignerAddress = false, validationHookData: Record = {}, customPaymasterHandler: CustomPaymasterHandler | undefined = undefined, + isPrivyCrossApp = false, ): Promise { const chain = client.chain; + if (isPrivyCrossApp) { + return signPrivyTransaction(client, args); + } + if (!chain?.serializers?.transaction) throw new BaseError('transaction serializer not found on chain.'); diff --git a/packages/agw-client/src/actions/signTypedData.ts b/packages/agw-client/src/actions/signTypedData.ts index 27415ce..728c280 100644 --- a/packages/agw-client/src/actions/signTypedData.ts +++ b/packages/agw-client/src/actions/signTypedData.ts @@ -2,21 +2,17 @@ import { type Account, BaseError, type Client, - encodeAbiParameters, + fromRlp, hashTypedData, type Hex, - parseAbiParameters, type Transport, type TypedData, type TypedDataDefinition, type WalletClient, } from 'viem'; -import type { SignTypedDataParameters } from 'viem/accounts'; -import { readContract, signTypedData as viemSignTypedData } from 'viem/actions'; +import { type SignTypedDataParameters } from 'viem/accounts'; import type { ChainEIP712 } from 'viem/chains'; -import { getAction } from 'viem/utils'; -import AGWAccountAbi from '../abis/AGWAccount.js'; import { EOA_VALIDATOR_ADDRESS, SESSION_KEY_VALIDATOR_ADDRESS, @@ -32,6 +28,7 @@ import { sendPrivySignTypedData } from './sendPrivyTransaction.js'; import { type CustomPaymasterHandler, signEip712TransactionInternal, + signTransaction, } from './signTransaction.js'; export async function signTypedData( @@ -40,34 +37,49 @@ export async function signTypedData( parameters: Omit, isPrivyCrossApp = false, ): Promise { - if (isPrivyCrossApp) return await sendPrivySignTypedData(client, parameters); - // if the typed data is already a zkSync EIP712 transaction, don't try to transform it // to an AGW typed signature, just pass it through to the signer. if (isEip712TypedData(parameters)) { - const rawSignature = await viemSignTypedData(signerClient, parameters); - // Match the expect signature format of the AGW smart account so the result can be - // directly used in eth_sendRawTransaction as the customSignature field - const hookData: Hex[] = []; - const validationHooks = await getAction( - client, - readContract, - 'readContract', - )({ - address: client.account.address, - abi: AGWAccountAbi, - functionName: 'listHooks', - args: [true], - }); - for (const _ of validationHooks) { - hookData.push('0x'); + const transformedTypedData = transformEip712TypedData(parameters); + + if (transformedTypedData.chainId !== client.chain.id) { + throw new BaseError('Chain ID mismatch in AGW typed signature'); } - const signature = encodeAbiParameters( - parseAbiParameters(['bytes', 'address', 'bytes[]']), - [rawSignature, EOA_VALIDATOR_ADDRESS, hookData], + const signedTransaction = await signTransaction( + client, + signerClient, + { + ...transformedTypedData, + chain: client.chain, + }, + EOA_VALIDATOR_ADDRESS, + false, + {}, + undefined, + isPrivyCrossApp, ); - return signature; + + if (!signedTransaction.startsWith('0x71')) { + throw new BaseError( + 'Expected RLP encoded EIP-712 transaction as signature', + ); + } + + const rlpSignature: Hex = `0x${signedTransaction.slice(4)}`; + + const signatureParts = fromRlp(rlpSignature, 'hex'); + if (signatureParts.length < 15) { + throw new BaseError( + 'Expected RLP encoded EIP-712 transaction with at least 15 fields', + ); + } + // This is somewhat not type safe as it assumes that the signature from signTransaction is an + // RLP encoded 712 transaction and that the customSignature field is the 15th field in the transaction. + // That being said, it's a safe assumption for the current use case. + return signatureParts[14] as Hex; + } else if (isPrivyCrossApp) { + return await sendPrivySignTypedData(client, parameters); } return await getAgwTypedSignature({ diff --git a/packages/agw-client/src/utils.ts b/packages/agw-client/src/utils.ts index 950b075..7d546bf 100644 --- a/packages/agw-client/src/utils.ts +++ b/packages/agw-client/src/utils.ts @@ -171,30 +171,37 @@ export function transformEip712TypedData( return { chainId: Number(typedData.domain.chainId), account: parseAccount( - toHex(typedData.message['from'] as bigint, { + toHex(BigInt(typedData.message['from'] as string), { size: 20, }), ), - to: toHex(typedData.message['to'] as bigint, { + to: toHex(BigInt(typedData.message['to'] as string), { size: 20, }), - gas: typedData.message['gasLimit'] as bigint, - gasPerPubdata: typedData.message['gasPerPubdataByteLimit'] as bigint, - maxFeePerGas: typedData.message['maxFeePerGas'] as bigint, - maxPriorityFeePerGas: typedData.message['maxPriorityFeePerGas'] as bigint, + gas: BigInt(typedData.message['gasLimit'] as string), + gasPerPubdata: BigInt( + typedData.message['gasPerPubdataByteLimit'] as string, + ), + maxFeePerGas: BigInt(typedData.message['maxFeePerGas'] as string), + maxPriorityFeePerGas: BigInt( + typedData.message['maxPriorityFeePerGas'] as string, + ), paymaster: - (typedData.message['paymaster'] as bigint) > 0n - ? toHex(typedData.message['paymaster'] as bigint, { + (typedData.message['paymaster'] as string) != '0' + ? toHex(BigInt(typedData.message['paymaster'] as string), { size: 20, }) : undefined, nonce: typedData.message['nonce'] as number, - value: typedData.message['value'] as bigint, - data: typedData.message['data'] as Hex, + value: BigInt(typedData.message['value'] as string), + data: + typedData.message['data'] === '0x0' + ? '0x' + : (typedData.message['data'] as Hex), factoryDeps: typedData.message['factoryDeps'] as Hex[], paymasterInput: - typedData.message['paymasterParams'] !== '0x' - ? (typedData.message['paymasterParams'] as Hex) + typedData.message['paymasterInput'] !== '0x' + ? (typedData.message['paymasterInput'] as Hex) : undefined, }; } diff --git a/packages/agw-client/src/walletActions.ts b/packages/agw-client/src/walletActions.ts index eaae39d..0f425a8 100644 --- a/packages/agw-client/src/walletActions.ts +++ b/packages/agw-client/src/walletActions.ts @@ -267,6 +267,10 @@ export function globalWalletActions< signerClient, args as SignEip712TransactionParameters, EOA_VALIDATOR_ADDRESS, + false, + {}, + undefined, + isPrivyCrossApp, ), signTypedData: ( args: Omit, diff --git a/packages/agw-client/test/src/actions/signTypedData.test.ts b/packages/agw-client/test/src/actions/signTypedData.test.ts index 69fd168..66f8736 100644 --- a/packages/agw-client/test/src/actions/signTypedData.test.ts +++ b/packages/agw-client/test/src/actions/signTypedData.test.ts @@ -19,7 +19,7 @@ import { } from 'viem'; import { toAccount } from 'viem/accounts'; import { getCode } from 'viem/actions'; -import { ChainEIP712 } from 'viem/zksync'; +import { ChainEIP712, getGeneralPaymasterInput } from 'viem/zksync'; import { describe, expect, it, vi } from 'vitest'; vi.mock('viem/actions', async (importOriginal) => { const actual = await importOriginal(); @@ -132,7 +132,9 @@ describe('signTypedData', async () => { value: 0n, data: '0x', factoryDeps: [], - paymasterInput: '0x', + paymasterInput: getGeneralPaymasterInput({ + innerInput: '0x', + }), }, }); expect(signedMessage).toBe( diff --git a/packages/agw-client/test/src/walletActions.test.ts b/packages/agw-client/test/src/walletActions.test.ts index 0e6beed..bc5267c 100644 --- a/packages/agw-client/test/src/walletActions.test.ts +++ b/packages/agw-client/test/src/walletActions.test.ts @@ -92,6 +92,10 @@ describe('globalWalletActions', () => { mockSignerClient, mockArgs, EOA_VALIDATOR_ADDRESS, + false, + {}, + undefined, + false, ); }); diff --git a/packages/agw-react/package.json b/packages/agw-react/package.json index c2a6b67..22852e5 100644 --- a/packages/agw-react/package.json +++ b/packages/agw-react/package.json @@ -79,7 +79,7 @@ "devDependencies": { "@abstract-foundation/agw-client": "workspace:*", "@privy-io/cross-app-connect": "^0.1.4", - "@privy-io/react-auth": "^2.0.5", + "@privy-io/react-auth": "^2.0.8", "@rainbow-me/rainbowkit": "^2.1.6", "@tanstack/query-core": "^5.56.2", "@types/react": ">=18.3.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ca071c..d28be4b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -101,8 +101,8 @@ importers: specifier: ^0.1.4 version: 0.1.4(xwqmugigierg3g7cqugnzqar5a) '@privy-io/react-auth': - specifier: ^2.0.5 - version: 2.0.5(@abstract-foundation/agw-client@packages+agw-client)(@solana/web3.js@1.95.3(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10))(@types/react@18.3.9)(bs58@5.0.0)(bufferutil@4.0.8)(permissionless@0.2.10(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(use-sync-external-store@1.2.0(react@18.3.1))(utf-8-validate@5.0.10)(zod@3.23.8) + specifier: ^2.0.8 + version: 2.0.8(@abstract-foundation/agw-client@packages+agw-client)(@solana/web3.js@1.95.3(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10))(@types/react@18.3.9)(bs58@5.0.0)(bufferutil@4.0.8)(permissionless@0.2.10(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(use-sync-external-store@1.2.0(react@18.3.1))(utf-8-validate@5.0.10)(zod@3.23.8) '@rainbow-me/rainbowkit': specifier: ^2.1.6 version: 2.1.6(@tanstack/react-query@5.56.2(react@18.3.1))(@types/react@18.3.9)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8))(wagmi@2.12.13(@tanstack/query-core@5.56.2)(@tanstack/react-query@5.56.2(react@18.3.1))(@types/react@18.3.9)(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react-native@0.75.3(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(@types/react@18.3.9)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(typescript@5.6.2)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.22.4)(typescript@5.6.2)(utf-8-validate@5.0.10)(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)) @@ -1663,8 +1663,8 @@ packages: resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@privy-io/api-base@1.4.2': - resolution: {integrity: sha512-YepVxiylommw2jBuUpdqm90Ebnx6H/HZODDFEpi2/G7lOWMN3GemFHllYC8sKzLIwbPuBqAo5ImvyootOXMCEA==} + '@privy-io/api-base@1.4.3': + resolution: {integrity: sha512-U++bkJmeXA7IzMU3Y+cUBnExpxwkOERmoD7C2q6C3UPu2getl/bGJMGeoiXPLvxziMRM4FVpQAhXCtj5OVB1iQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} '@privy-io/cross-app-connect@0.1.4': @@ -1691,8 +1691,8 @@ packages: '@wagmi/core': optional: true - '@privy-io/js-sdk-core@0.41.0': - resolution: {integrity: sha512-4PBAP9xyvWb8PA8nEyAHMldw0U9LhVSEt/pcz/Hi41+UIoHczDWizxnIJbioYBEoabMGrScjJPKHX8rHZF/XgA==} + '@privy-io/js-sdk-core@0.41.2': + resolution: {integrity: sha512-pChv11A9WjUdIxfQWpPXxmomgs+TCiyBQiLXcfpiF7ZOOAjcNlVLfCe136wrHrpc4NFS6G91z2Xx8cSaF7mrvQ==} peerDependencies: permissionless: ^0.2.10 viem: ^2.21.36 @@ -1702,12 +1702,12 @@ packages: viem: optional: true - '@privy-io/public-api@2.18.1': - resolution: {integrity: sha512-CF4MhEE/gocPST2y+keb0Xp4HcJ1ecfbB0pw0Nms1SKlv2hgPG1Lx6Djo+NSu2NJ5l3W+IcEoJzJU/xRcoyW+Q==} + '@privy-io/public-api@2.18.3': + resolution: {integrity: sha512-XbgWh0LgHGL/J+yzF8jKioJqwlvTdtBcqfOAtuA9ZVF2FW3rtgfWe3ot3v61QMzhIntXhY5uIVBC2Hn8EwDR6A==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} - '@privy-io/react-auth@2.0.5': - resolution: {integrity: sha512-rvWmTGljKMmKr+ewzxkYtosnC41H1eDqT9r4/02C0SVhC2SR2S0QnmmK77VmLbGrjD3pp6qNRUXZWXx2Ybgusg==} + '@privy-io/react-auth@2.0.8': + resolution: {integrity: sha512-I6mMjrHC0LY0QLGHRfW/0T6pcGlXYBcKHYEV/SbCUYpvwozu6U5qOCv+USMdjHcl5mXoeLquX8Nrip5fpMN+PQ==} peerDependencies: '@abstract-foundation/agw-client': ^1.0.0 '@solana/web3.js': ^1.95.8 @@ -8714,7 +8714,7 @@ snapshots: '@pkgr/core@0.1.1': {} - '@privy-io/api-base@1.4.2': + '@privy-io/api-base@1.4.3': dependencies: zod: 3.23.8 @@ -8738,7 +8738,7 @@ snapshots: '@rainbow-me/rainbowkit': 2.1.6(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.9)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8))(wagmi@2.12.13(@tanstack/query-core@5.59.20)(@tanstack/react-query@5.59.20(react@18.3.1))(@types/react@18.3.9)(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react-native@0.75.3(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(@types/react@18.3.9)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.3.1)(typescript@5.6.2)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.22.4)(typescript@5.6.2)(utf-8-validate@5.0.10)(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)) '@wagmi/core': 2.13.6(@tanstack/query-core@5.59.20)(@types/react@18.3.9)(react@18.3.1)(typescript@5.6.2)(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8)) - '@privy-io/js-sdk-core@0.41.0(bufferutil@4.0.8)(permissionless@0.2.10(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8)))(utf-8-validate@5.0.10)(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8))': + '@privy-io/js-sdk-core@0.41.2(bufferutil@4.0.8)(permissionless@0.2.10(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8)))(utf-8-validate@5.0.10)(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8))': dependencies: '@ethersproject/abstract-signer': 5.7.0 '@ethersproject/bignumber': 5.7.0 @@ -8746,8 +8746,8 @@ snapshots: '@ethersproject/providers': 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@ethersproject/transactions': 5.7.0 '@ethersproject/units': 5.7.0 - '@privy-io/api-base': 1.4.2 - '@privy-io/public-api': 2.18.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@privy-io/api-base': 1.4.3 + '@privy-io/public-api': 2.18.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) eventemitter3: 5.0.1 fetch-retry: 5.0.6 jose: 4.15.9 @@ -8762,9 +8762,9 @@ snapshots: - bufferutil - utf-8-validate - '@privy-io/public-api@2.18.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)': + '@privy-io/public-api@2.18.3(bufferutil@4.0.8)(utf-8-validate@5.0.10)': dependencies: - '@privy-io/api-base': 1.4.2 + '@privy-io/api-base': 1.4.3 bs58: 5.0.0 ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) libphonenumber-js: 1.11.11 @@ -8773,7 +8773,7 @@ snapshots: - bufferutil - utf-8-validate - '@privy-io/react-auth@2.0.5(@abstract-foundation/agw-client@packages+agw-client)(@solana/web3.js@1.95.3(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10))(@types/react@18.3.9)(bs58@5.0.0)(bufferutil@4.0.8)(permissionless@0.2.10(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(use-sync-external-store@1.2.0(react@18.3.1))(utf-8-validate@5.0.10)(zod@3.23.8)': + '@privy-io/react-auth@2.0.8(@abstract-foundation/agw-client@packages+agw-client)(@solana/web3.js@1.95.3(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10))(@types/react@18.3.9)(bs58@5.0.0)(bufferutil@4.0.8)(permissionless@0.2.10(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(use-sync-external-store@1.2.0(react@18.3.1))(utf-8-validate@5.0.10)(zod@3.23.8)': dependencies: '@coinbase/wallet-sdk': 4.0.3 '@floating-ui/react': 0.26.25(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -8781,7 +8781,7 @@ snapshots: '@heroicons/react': 2.1.5(react@18.3.1) '@marsidev/react-turnstile': 0.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@metamask/eth-sig-util': 6.0.2 - '@privy-io/js-sdk-core': 0.41.0(bufferutil@4.0.8)(permissionless@0.2.10(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8)))(utf-8-validate@5.0.10)(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8)) + '@privy-io/js-sdk-core': 0.41.2(bufferutil@4.0.8)(permissionless@0.2.10(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8)))(utf-8-validate@5.0.10)(viem@2.22.14(bufferutil@4.0.8)(typescript@5.6.2)(utf-8-validate@5.0.10)(zod@3.23.8)) '@simplewebauthn/browser': 9.0.1 '@solana/wallet-adapter-base': 0.9.23(@solana/web3.js@1.95.3(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)) '@solana/wallet-standard-wallet-adapter-base': 1.1.2(@solana/web3.js@1.95.3(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10))(bs58@5.0.0)