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'}