Skip to content

Commit a60ed6f

Browse files
committed
feat: use paymaster for nft minting
1 parent 7727e55 commit a60ed6f

File tree

3 files changed

+27
-25
lines changed

3 files changed

+27
-25
lines changed

examples/nft-quest/composables/useMintNft.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,10 @@ export const useMintNft = async (_address: MaybeRef<Address>) => {
77
const runtimeConfig = useRuntimeConfig();
88
const clientStore = useClientStore();
99

10-
// WORKAROUND: Use throw-away client (rich account #0) to mint
11-
// TODO: Use passkey client with bundler once factory contracts are deployed
12-
const client = clientStore.getThrowAwayClient();
10+
const client = clientStore.getClient();
1311

1412
const mintingForAddress = address.value;
1513

16-
// Submit mint transaction directly (not via bundler)
1714
const hash = await client.writeContract({
1815
address: runtimeConfig.public.contracts.nft as Address,
1916
abi: nftAbi,

examples/nft-quest/nuxt.config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ export default defineNuxtConfig({
3535
contracts: {
3636
nft: "0x4D533d3B20b50b57268f189F93bFaf8B39c36AB6",
3737
paymaster: "0x60eef092977DF2738480a6986e2aCD10236b1FA7",
38+
webauthnValidator: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
3839
},
40+
bundlerUrl: "http://localhost:4337",
3941
baseUrl: "https://nft.zksync.dev",
4042
authServerUrl: "https://auth-test.zksync.dev/confirm",
4143
explorerUrl: "https://sepolia.explorer.zksync.io",
@@ -73,7 +75,9 @@ export default defineNuxtConfig({
7375
contracts: {
7476
nft: process.env.NUXT_PUBLIC_CONTRACTS_NFT || "0x4c07ce6454D5340591f62fD7d3978B6f42Ef953e",
7577
paymaster: process.env.NUXT_PUBLIC_CONTRACTS_PAYMASTER || "",
78+
webauthnValidator: process.env.NUXT_PUBLIC_CONTRACTS_WEBAUTHN_VALIDATOR || "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
7679
},
80+
bundlerUrl: process.env.NUXT_PUBLIC_BUNDLER_URL || "http://localhost:4337",
7781
baseUrl: "http://localhost:3006",
7882
authServerUrl: "http://localhost:3002/confirm",
7983
explorerUrl: "http://localhost:3010",

examples/nft-quest/stores/client.ts

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import type { Address, Hex } from "viem";
2-
import { createPublicClient, createWalletClient, http, publicActions } from "viem";
2+
import { createPublicClient, http } from "viem";
33
import { createBundlerClient } from "viem/account-abstraction";
4-
import { privateKeyToAccount } from "viem/accounts";
54
import type { Chain } from "viem/chains";
5+
import { getGeneralPaymasterInput } from "viem/zksync";
66
import { createPasskeyClient } from "zksync-sso-4337/client";
77

8-
import contractsConfig from "../contracts-anvil.json";
9-
108
// Anvil chain configuration (chain ID 31337)
119
const anvilChain: Chain = {
1210
id: 31337,
@@ -31,11 +29,26 @@ export const useClientStore = defineStore("client", () => {
3129

3230
const getBundlerClient = () => {
3331
const publicClient = getPublicClient();
32+
const runtimeConfig = useRuntimeConfig();
33+
const paymasterAddress = runtimeConfig.public.contracts.paymaster as Address;
34+
const bundlerUrl = runtimeConfig.public.bundlerUrl as string;
3435

3536
return createBundlerClient({
3637
client: publicClient,
3738
chain,
38-
transport: http(contractsConfig.bundlerUrl),
39+
transport: http(bundlerUrl),
40+
paymaster: {
41+
async getPaymasterData() {
42+
return {
43+
paymasterAndData: `${paymasterAddress}${getGeneralPaymasterInput({ innerInput: "0x" }).substring(2)}` as Hex,
44+
};
45+
},
46+
async getPaymasterStubData() {
47+
return {
48+
paymasterAndData: `${paymasterAddress}${getGeneralPaymasterInput({ innerInput: "0x" }).substring(2)}` as Hex,
49+
};
50+
},
51+
},
3952
userOperation: {
4053
async estimateFeesPerGas() {
4154
const feesPerGas = await publicClient.estimateFeesPerGas();
@@ -54,12 +67,13 @@ export const useClientStore = defineStore("client", () => {
5467
if (!address.value) throw new Error("Address is not set");
5568
if (!credentialId.value) throw new Error("Credential ID is not set");
5669

70+
const runtimeConfig = useRuntimeConfig();
5771
const bundlerClient = getBundlerClient();
5872

5973
const client = createPasskeyClient({
6074
account: {
6175
address: address.value,
62-
validatorAddress: contractsConfig.webauthnValidator as Address,
76+
validatorAddress: runtimeConfig.public.contracts.webauthnValidator as Address,
6377
credentialId: credentialId.value,
6478
rpId: window.location.hostname,
6579
origin: window.location.origin,
@@ -72,31 +86,20 @@ export const useClientStore = defineStore("client", () => {
7286
return client;
7387
};
7488

75-
const getThrowAwayClient = () => {
76-
const throwAwayClient = createWalletClient({
77-
account: privateKeyToAccount(
78-
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", // Anvil rich account
79-
),
80-
chain,
81-
transport: http(),
82-
})
83-
.extend(publicActions);
84-
return throwAwayClient;
85-
};
86-
8789
const getConfigurableClient = ({
8890
address: addr,
8991
credentialId: credId,
9092
}: {
9193
address: Address;
9294
credentialId: Hex;
9395
}) => {
96+
const runtimeConfig = useRuntimeConfig();
9497
const bundlerClient = getBundlerClient();
9598

9699
return createPasskeyClient({
97100
account: {
98101
address: addr,
99-
validatorAddress: contractsConfig.webauthnValidator as Address,
102+
validatorAddress: runtimeConfig.public.contracts.webauthnValidator as Address,
100103
credentialId: credId,
101104
rpId: window.location.hostname,
102105
origin: window.location.origin,
@@ -109,11 +112,9 @@ export const useClientStore = defineStore("client", () => {
109112

110113
return {
111114
chain,
112-
contractsConfig,
113115
getPublicClient,
114116
getBundlerClient,
115117
getClient,
116-
getThrowAwayClient,
117118
getConfigurableClient,
118119
};
119120
});

0 commit comments

Comments
 (0)