diff --git a/apps/dapp/package.json b/apps/dapp/package.json index 3f9439a..7167869 100644 --- a/apps/dapp/package.json +++ b/apps/dapp/package.json @@ -23,11 +23,13 @@ "firebase-tools": "^13.5.1", "helpers": "workspace:*", "lucide-react": "^0.358.0", + "permissionless": "^0.1.10", "react": "^18.2.0", "react-dom": "^18.2.0", "tailwind-merge": "^2.2.1", "tailwindcss": "^3.4.1", "tailwindcss-animate": "^1.0.7", - "typescript": "^5.4.2" + "typescript": "^5.4.2", + "viem": "^2.8.10" } } \ No newline at end of file diff --git a/apps/dapp/src/components/deploy-account-button.tsx b/apps/dapp/src/components/deploy-account-button.tsx new file mode 100644 index 0000000..5d33890 --- /dev/null +++ b/apps/dapp/src/components/deploy-account-button.tsx @@ -0,0 +1,16 @@ +import { Button } from "@/components/ui/button"; +import { createSafe4337Account } from "@/lib/safe-account"; + +export function DeployAccountButton() { + return ( + + ); +} diff --git a/apps/dapp/src/env.d.ts b/apps/dapp/src/env.d.ts index acef35f..3e489ef 100644 --- a/apps/dapp/src/env.d.ts +++ b/apps/dapp/src/env.d.ts @@ -1,2 +1,3 @@ /// /// +PUBLIC_PIMLICO_API_KEY \ No newline at end of file diff --git a/apps/dapp/src/lib/permissionless.ts b/apps/dapp/src/lib/permissionless.ts new file mode 100644 index 0000000..21f3161 --- /dev/null +++ b/apps/dapp/src/lib/permissionless.ts @@ -0,0 +1,70 @@ +import { createBundlerClient, createSmartAccountClient } from "permissionless" +import { baseSepolia } from "viem/chains" +import { createPublicClient, createWalletClient, http } from "viem" +import { createPimlicoPaymasterClient } from "permissionless/clients/pimlico"; +import { privateKeyToSimpleSmartAccount, signerToSafeSmartAccount } from "permissionless/accounts"; +import { privateKeyToAccount } from "viem/accounts"; + +// ! Dont do this in prod +const pimlicoApiKey = import.meta.env.PUBLIC_PIMLICO_API_KEY +const privateKey = import.meta.env.PUBLIC_PRIVATE_KEY + +const pimlicoTransport = (version: 'v1' | 'v2') => http(`https://api.pimlico.io/${version}/${baseSepolia.id}/rpc?apikey=${pimlicoApiKey}`) + +export const ENTRYPOINT_ADDRESS_V07 = '0x0000000071727De22E5E9d8BAf0edAc6f37da032'; +export const ENTRYPOINT_ADDRESS_V06 = '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789'; + +// create clients -------------------------------------------- + +export const publicClient = createPublicClient({ + transport: http(baseSepolia.rpcUrls.default.http[0]) +}); + +export const walletClient = createWalletClient({ + chain: baseSepolia, + transport: http(baseSepolia.rpcUrls.default.http[0]), + account: privateKeyToAccount(privateKey) +}); + +export const bundlerClient = createBundlerClient({ + chain: baseSepolia, + transport: pimlicoTransport('v2'), + entryPoint: ENTRYPOINT_ADDRESS_V07 +}) + +export const paymasterClient = createPimlicoPaymasterClient({ + transport: pimlicoTransport('v2'), + entryPoint: ENTRYPOINT_ADDRESS_V06 +}); + +// create account & account client -------------------------------------------- + +export const simpleAccount = await privateKeyToSimpleSmartAccount(publicClient, { + privateKey: privateKey, + factoryAddress: "0x15Ba39375ee2Ab563E8873C8390be6f2E2F50232", + entryPoint: ENTRYPOINT_ADDRESS_V07 +}); + +export const safeAccount = await signerToSafeSmartAccount(publicClient, { + entryPoint: ENTRYPOINT_ADDRESS_V06, + signer: privateKeyToAccount(privateKey), + saltNonce: 0n, // optional + safeVersion: "1.4.1", + //address: "0x...", // optional, only if you are using an already created account +}) + +export const smartAccountClient = createSmartAccountClient({ + account: simpleAccount, + entryPoint: ENTRYPOINT_ADDRESS_V07, + chain: baseSepolia, + bundlerTransport: pimlicoTransport('v2'), +}); + +export const safeAccountClient = createSmartAccountClient({ + account: safeAccount, + entryPoint: ENTRYPOINT_ADDRESS_V06, + chain: baseSepolia, + bundlerTransport: pimlicoTransport('v2'), +}); + + diff --git a/apps/dapp/src/lib/safe-account.ts b/apps/dapp/src/lib/safe-account.ts new file mode 100644 index 0000000..a7a1112 --- /dev/null +++ b/apps/dapp/src/lib/safe-account.ts @@ -0,0 +1,34 @@ +import { encodeFunctionData } from "viem" +import { walletClient, publicClient } from './permissionless' + +// abis -------------------------------------------- + +const ONIT_FACTORY_ADDRESS = '0x42ab880ea77fc7a09eb6ba0fe82fbc9901c114b6' + +const createSafe4337Abi = [ + { "type": "function", "name": "createSafe4337", "inputs": [{ "name": "passkeyPublicKey", "type": "uint256[2]", "internalType": "uint256[2]" }, { "name": "nonce", "type": "uint256", "internalType": "uint256" }], "outputs": [{ "name": "onitAccountAddress", "type": "address", "internalType": "address" }], "stateMutability": "nonpayable" } +] + +// formatting calls -------------------------------------------- + +export const createSafe4337Account = async () => { + const { request } = await publicClient.simulateContract({ + account: walletClient.account, + address: ONIT_FACTORY_ADDRESS, + abi: createSafe4337Abi, + functionName: 'createSafe4337', + args: [[1n, 2n], 3n], + }) + console.log({ request }) + + const deployResponse = await walletClient.writeContract(request) + console.log({ deployResponse }) + + return deployResponse +} + +const formatFactoryCreateSafe4337Calldata = (x: bigint, y: bigint, nonce: bigint) => { + const createSafe4337Calldata = encodeFunctionData({ abi: createSafe4337Abi, functionName: "createSafe4337", args: [[x, y], nonce] }) + console.log(createSafe4337Calldata) + return createSafe4337Calldata +} \ No newline at end of file diff --git a/apps/dapp/src/pages/index.astro b/apps/dapp/src/pages/index.astro index a48b981..f79595b 100644 --- a/apps/dapp/src/pages/index.astro +++ b/apps/dapp/src/pages/index.astro @@ -1,6 +1,10 @@ --- import "../../public/global.css"; import { CreatePaymentButton } from "@/components/create-payment-button"; +import { DeployAccountButton } from "@/components/deploy-account-button"; +import { getPaymentOrigin } from "@/lib/utils"; + +const paymentOrigin = getPaymentOrigin(); import WalletIframeDialog from "@/components/wallet-iframe-dialog.astro"; --- @@ -17,6 +21,14 @@ import WalletIframeDialog from "@/components/wallet-iframe-dialog.astro";

SPC dApp

+ + + + +
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 813f865..d0007c2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,6 +53,9 @@ importers: lucide-react: specifier: ^0.358.0 version: 0.358.0(react@18.2.0) + permissionless: + specifier: ^0.1.10 + version: 0.1.10(viem@2.8.10) react: specifier: ^18.2.0 version: 18.2.0 @@ -71,6 +74,9 @@ importers: typescript: specifier: ^5.4.2 version: 5.4.2 + viem: + specifier: ^2.8.10 + version: 2.8.10(typescript@5.4.2)(zod@3.22.4) apps/wallet: dependencies: @@ -167,6 +173,10 @@ importers: packages: + /@adraffy/ens-normalize@1.10.0: + resolution: {integrity: sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==} + dev: false + /@alloc/quick-lru@5.2.0: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -1253,6 +1263,17 @@ packages: resolution: {integrity: sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==} dev: false + /@noble/curves@1.2.0: + resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} + dependencies: + '@noble/hashes': 1.3.2 + dev: false + + /@noble/hashes@1.3.2: + resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} + engines: {node: '>= 16'} + dev: false + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1606,6 +1627,25 @@ packages: dev: false optional: true + /@scure/base@1.1.5: + resolution: {integrity: sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==} + dev: false + + /@scure/bip32@1.3.2: + resolution: {integrity: sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==} + dependencies: + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@scure/base': 1.1.5 + dev: false + + /@scure/bip39@1.2.1: + resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==} + dependencies: + '@noble/hashes': 1.3.2 + '@scure/base': 1.1.5 + dev: false + /@shikijs/core@1.2.0: resolution: {integrity: sha512-OlFvx+nyr5C8zpcMBnSGir0YPD6K11uYhouqhNmm1qLiis4GA7SsGtu07r9gKS9omks8RtQqHrJL4S+lqWK01A==} dev: false @@ -1946,6 +1986,21 @@ packages: dev: false optional: true + /abitype@1.0.0(typescript@5.4.2)(zod@3.22.4): + resolution: {integrity: sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + dependencies: + typescript: 5.4.2 + zod: 3.22.4 + dev: false + /abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -4926,6 +4981,14 @@ packages: - encoding dev: false + /isows@1.0.3(ws@8.13.0): + resolution: {integrity: sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==} + peerDependencies: + ws: '*' + dependencies: + ws: 8.13.0 + dev: false + /jackspeak@2.3.6: resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} engines: {node: '>=14'} @@ -6552,6 +6615,14 @@ packages: resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} dev: false + /permissionless@0.1.10(viem@2.8.10): + resolution: {integrity: sha512-LVjGVLRfARHhuWSktiO5wd2tA0iTzP+Se8oDKRVyzb5Z/X4jCL+3hqWJMeERkjn3bOK0al2cv55sIABFOo+XKg==} + peerDependencies: + viem: ^2.0.0 + dependencies: + viem: 2.8.10(typescript@5.4.2)(zod@3.22.4) + dev: false + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: false @@ -8326,6 +8397,29 @@ packages: vfile-message: 4.0.2 dev: false + /viem@2.8.10(typescript@5.4.2)(zod@3.22.4): + resolution: {integrity: sha512-rhIdRXWLPMUPjL2aI7oYNn4PrgEimbf2rxEkTjty0L+ZBIvPgKAOZFUeStpAfdWouTDO4yM84Xk4Hh2hrwiK9A==} + peerDependencies: + typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@adraffy/ens-normalize': 1.10.0 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@scure/bip32': 1.3.2 + '@scure/bip39': 1.2.1 + abitype: 1.0.0(typescript@5.4.2)(zod@3.22.4) + isows: 1.0.3(ws@8.13.0) + typescript: 5.4.2 + ws: 8.13.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + dev: false + /vite@5.1.6: resolution: {integrity: sha512-yYIAZs9nVfRJ/AiOLCA91zzhjsHUgMjB+EigzFb6W2XTLO8JixBCKCjvhKZaye+NKYHCrkv3Oh50dH9EdLU2RA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -8697,6 +8791,19 @@ packages: optional: true dev: false + /ws@8.13.0: + resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /ws@8.16.0: resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} engines: {node: '>=10.0.0'}