Skip to content

Commit 65c5723

Browse files
authored
Transition dca dapp to base sepolia (#708)
* change chain to baseSepolia * refactor userOpBuilder and cosigner service * update DonutContract address * chores:run prettier * fix functionName
1 parent 4cceabb commit 65c5723

File tree

10 files changed

+78
-255
lines changed

10 files changed

+78
-255
lines changed

advanced/dapps/dca-dapp-demo/src/app/api/dca/execute/route.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { CoSignerApiError } from "@/utils/WalletConnectCosignerUtils";
77
import { NextResponse } from "next/server";
88
import { encodeFunctionData, parseEther } from "viem";
99
import { GrantPermissionsReturnType } from "viem/experimental";
10-
import { sepolia } from "viem/chains";
10+
import { baseSepolia } from "viem/chains";
1111
import { DCAFormSchemaType } from "@/schema/DCAFormSchema";
1212

1313
export async function POST(request: Request) {
@@ -20,7 +20,8 @@ export async function POST(request: Request) {
2020
permissions: GrantPermissionsReturnType;
2121
pci: string;
2222
} = await request.json();
23-
const APPLICATION_PRIVATE_KEY = process.env.APPLICATION_PRIVATE_KEY as `0x${string}`;
23+
const APPLICATION_PRIVATE_KEY = process.env
24+
.APPLICATION_PRIVATE_KEY as `0x${string}`;
2425

2526
try {
2627
if (!APPLICATION_PRIVATE_KEY) {
@@ -61,7 +62,7 @@ export async function POST(request: Request) {
6162
ecdsaPrivateKey: APPLICATION_PRIVATE_KEY,
6263
pci,
6364
permissions,
64-
chain: sepolia,
65+
chain: baseSepolia,
6566
actions: purchaseDonutCallDataExecution,
6667
});
6768

advanced/dapps/dca-dapp-demo/src/app/api/signer/route.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { privateKeyToAccount } from "viem/accounts";
33

44
export function GET() {
55
try {
6-
const APPLICATION_PRIVATE_KEY = process.env.APPLICATION_PRIVATE_KEY as `0x${string}`;
6+
const APPLICATION_PRIVATE_KEY = process.env
7+
.APPLICATION_PRIVATE_KEY as `0x${string}`;
78
const account = privateKeyToAccount(APPLICATION_PRIVATE_KEY);
89

910
return NextResponse.json({ key: account.publicKey });

advanced/dapps/dca-dapp-demo/src/hooks/useDCA.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
hexStringToBase64,
55
} from "../utils/EncodingUtils";
66
import { walletActionsErc7715 } from "viem/experimental";
7-
import { createPublicClient, custom } from "viem";
7+
import { createPublicClient, custom, zeroAddress } from "viem";
88
import { WalletConnectCosigner } from "../utils/WalletConnectCosignerUtils";
99
import { useDcaApplicationContext } from "../context/DcaApplicationContextProvider";
1010
import { DCAFormSchemaType } from "@/schema/DCAFormSchema";
@@ -83,8 +83,7 @@ export function useDCA() {
8383
},
8484
},
8585
signerData: {
86-
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
87-
userOpBuilder: approvedPermissions.signerData?.userOpBuilder!,
86+
userOpBuilder: zeroAddress,
8887
},
8988
permissionsContext: approvedPermissions.permissionsContext,
9089
factory: approvedPermissions.factory || "",

advanced/dapps/dca-dapp-demo/src/utils/ChainsUtil.ts

Lines changed: 0 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -8,110 +8,6 @@ function getBlockchainApiRpcUrl(chainId: number) {
88
return `https://rpc.walletconnect.org/v1/?chainId=eip155:${chainId}&projectId=${process.env["NEXT_PUBLIC_PROJECT_ID"]}`;
99
}
1010

11-
export const mainnet = {
12-
chainId: 1,
13-
name: "Ethereum",
14-
currency: "ETH",
15-
explorerUrl: "https://etherscan.io",
16-
rpcUrl: getBlockchainApiRpcUrl(1),
17-
};
18-
19-
export const arbitrum = {
20-
chainId: 42161,
21-
name: "Arbitrum",
22-
currency: "ETH",
23-
explorerUrl: "https://arbiscan.io",
24-
rpcUrl: getBlockchainApiRpcUrl(42161),
25-
};
26-
27-
export const avalanche = {
28-
chainId: 43114,
29-
name: "Avalanche",
30-
currency: "AVAX",
31-
explorerUrl: "https://snowtrace.io",
32-
rpcUrl: getBlockchainApiRpcUrl(43114),
33-
};
34-
35-
export const binanceSmartChain = {
36-
chainId: 56,
37-
name: "Binance Smart Chain",
38-
currency: "BNB",
39-
explorerUrl: "https://bscscan.com",
40-
rpcUrl: getBlockchainApiRpcUrl(56),
41-
};
42-
43-
export const optimism = {
44-
chainId: 10,
45-
name: "Optimism",
46-
currency: "ETH",
47-
explorerUrl: "https://optimistic.etherscan.io",
48-
rpcUrl: getBlockchainApiRpcUrl(10),
49-
};
50-
51-
export const polygon = {
52-
chainId: 137,
53-
name: "Polygon",
54-
currency: "MATIC",
55-
explorerUrl: "https://polygonscan.com",
56-
rpcUrl: getBlockchainApiRpcUrl(137),
57-
};
58-
59-
export const gnosis = {
60-
chainId: 100,
61-
name: "Gnosis",
62-
currency: "xDAI",
63-
explorerUrl: "https://gnosis.blockscout.com",
64-
rpcUrl: getBlockchainApiRpcUrl(100),
65-
};
66-
67-
export const zkSync = {
68-
chainId: 324,
69-
name: "ZkSync",
70-
currency: "ETH",
71-
explorerUrl: "https://explorer.zksync.io",
72-
rpcUrl: getBlockchainApiRpcUrl(324),
73-
};
74-
75-
export const zora = {
76-
chainId: 7777777,
77-
name: "Zora",
78-
currency: "ETH",
79-
explorerUrl: "https://explorer.zora.energy",
80-
rpcUrl: getBlockchainApiRpcUrl(7777777),
81-
};
82-
83-
export const celo = {
84-
chainId: 42220,
85-
name: "Celo",
86-
currency: "CELO",
87-
explorerUrl: "https://explorer.celo.org/mainnet",
88-
rpcUrl: getBlockchainApiRpcUrl(42220),
89-
};
90-
91-
export const base = {
92-
chainId: 8453,
93-
name: "Base",
94-
currency: "BASE",
95-
explorerUrl: "https://basescan.org",
96-
rpcUrl: getBlockchainApiRpcUrl(8453),
97-
};
98-
99-
export const aurora = {
100-
chainId: 1313161554,
101-
name: "Aurora",
102-
currency: "ETH",
103-
explorerUrl: "https://explorer.aurora.dev",
104-
rpcUrl: getBlockchainApiRpcUrl(1313161554),
105-
};
106-
107-
export const sepolia = {
108-
chainId: 11155111,
109-
name: "Sepolia",
110-
currency: "ETH",
111-
explorerUrl: "https://sepolia.etherscan.io",
112-
rpcUrl: getBlockchainApiRpcUrl(11155111),
113-
};
114-
11511
export const baseSepolia = {
11612
chainId: 84532,
11713
name: "Base Sepolia",
@@ -120,30 +16,6 @@ export const baseSepolia = {
12016
rpcUrl: getBlockchainApiRpcUrl(84532),
12117
};
12218

123-
export const solana = {
124-
chainId: "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
125-
name: "Solana",
126-
currency: "SOL",
127-
explorerUrl: "https://solscan.io",
128-
rpcUrl: "https://rpc.walletconnect.org/v1",
129-
};
130-
131-
export const solanaTestnet = {
132-
chainId: "4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z",
133-
name: "Solana Testnet",
134-
currency: "SOL",
135-
explorerUrl: "https://explorer.solana.com/?cluster=testnet",
136-
rpcUrl: "https://rpc.walletconnect.org/v1",
137-
};
138-
139-
export const solanaDevnet = {
140-
chainId: "EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
141-
name: "Solana Devnet",
142-
currency: "SOL",
143-
explorerUrl: "https://explorer.solana.com/?cluster=devnet",
144-
rpcUrl: "https://rpc.walletconnect.org/v1",
145-
};
146-
14719
export function getChain(id: number) {
14820
const chains = Object.values(viemChains) as viemChains.Chain[];
14921

advanced/dapps/dca-dapp-demo/src/utils/DCAUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export function getSampleAsyncDCAPermissions(
3737
target: donutContractAddress,
3838
abi: donutContractAbi,
3939
valueLimit: parseEther("10").toString(),
40-
functionName: "function purchase()",
40+
functionName: "purchase(uint256)",
4141
},
4242
policies: [],
4343
},

advanced/dapps/dca-dapp-demo/src/utils/DonutContract.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,4 @@ export const abi = [
7070
},
7171
];
7272

73-
export const address = "0xfcfCFD8D9f4A23D8DD11b03b212B69262A3ba1b8";
73+
export const address = "0x2E65BAfA07238666c3b239E94F32DaD3cDD6498D";

advanced/dapps/dca-dapp-demo/src/utils/ERC7715PermissionsAsyncUtils.ts

Lines changed: 22 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ import { type GrantPermissionsReturnType } from "viem/experimental";
22
import { bigIntReplacer } from "./CommonUtils";
33
import { signMessage } from "viem/accounts";
44
import { type Chain } from "viem";
5-
import { WalletConnectCosigner } from "./WalletConnectCosignerUtils";
65
import {
76
buildUserOp,
7+
sendUserOp,
88
type Call,
9-
type FillUserOpResponse,
109
} from "./UserOpBuilderServiceUtils";
1110

1211
export type MultikeySigner = {
@@ -16,102 +15,52 @@ export type MultikeySigner = {
1615
};
1716
};
1817

19-
async function prepareUserOperationWithPermissions(args: {
18+
export async function executeActionsWithECDSAAndCosignerPermissions(args: {
2019
actions: Call[];
20+
ecdsaPrivateKey: `0x${string}`;
2121
chain: Chain;
2222
permissions: GrantPermissionsReturnType;
23-
}): Promise<FillUserOpResponse> {
24-
const { actions, chain, permissions } = args;
23+
pci: string;
24+
}): Promise<`0x${string}`> {
25+
const { ecdsaPrivateKey, actions, chain, permissions, pci } = args;
26+
if (!pci) {
27+
throw new Error("No WC_COSIGNER PCI data available");
28+
}
2529
if (!permissions) {
2630
throw new Error("No permissions available");
2731
}
2832
const { signerData, permissionsContext } = permissions;
2933

30-
if (
31-
!signerData?.userOpBuilder ||
32-
!signerData.submitToAddress ||
33-
!permissionsContext
34-
) {
34+
if (!signerData?.submitToAddress || !permissionsContext) {
3535
throw new Error(
3636
`Invalid permissions ${JSON.stringify(permissions, bigIntReplacer)}`,
3737
);
3838
}
39+
const accountAddress = signerData.submitToAddress;
3940

4041
const filledUserOp = await buildUserOp({
41-
account: signerData.submitToAddress,
42+
account: accountAddress,
4243
chainId: chain.id,
4344
calls: actions,
4445
capabilities: {
4546
permissions: { context: permissionsContext as `0x${string}` },
4647
},
4748
});
4849

49-
return filledUserOp;
50-
}
51-
52-
async function signUserOperationWithECDSAKey(args: {
53-
ecdsaPrivateKey: `0x${string}`;
54-
userOpHash: `0x${string}`;
55-
}): Promise<`0x${string}`> {
56-
const { ecdsaPrivateKey, userOpHash } = args;
50+
const userOp = filledUserOp.userOp;
5751

58-
const dappSignatureOnUserOp = await signMessage({
52+
const dappSignature = await signMessage({
5953
privateKey: ecdsaPrivateKey,
60-
message: { raw: userOpHash },
54+
message: { raw: filledUserOp.hash },
6155
});
56+
userOp.signature = dappSignature;
6257

63-
return dappSignatureOnUserOp;
64-
}
65-
66-
export async function executeActionsWithECDSAAndCosignerPermissions(args: {
67-
actions: Call[];
68-
ecdsaPrivateKey: `0x${string}`;
69-
chain: Chain;
70-
permissions: GrantPermissionsReturnType;
71-
pci: string;
72-
}): Promise<`0x${string}`> {
73-
const { ecdsaPrivateKey, actions, chain, permissions, pci } = args;
74-
const accountAddress = permissions?.signerData?.submitToAddress;
75-
if (!accountAddress) {
76-
throw new Error(`Unable to get account details from granted permission`);
77-
}
78-
79-
if (!pci) {
80-
throw new Error("No WC_COSIGNER PCI data available");
81-
}
82-
const caip10Address = `eip155:${chain?.id}:${accountAddress}`;
83-
const filledUserOp = await prepareUserOperationWithPermissions({
84-
actions,
85-
chain,
86-
permissions,
87-
});
88-
const userOp = filledUserOp.userOp;
89-
90-
const dappSignature = await signUserOperationWithECDSAKey({
91-
ecdsaPrivateKey,
92-
userOpHash: filledUserOp.hash,
58+
const sendUserOpResponse = await sendUserOp({
59+
userOp,
60+
pci,
61+
chainId: chain.id,
62+
permissionsContext: permissionsContext as `0x${string}`,
9363
});
9464

95-
userOp.signature = dappSignature;
96-
const walletConnectCosigner = new WalletConnectCosigner();
97-
const cosignResponse = await walletConnectCosigner.coSignUserOperation(
98-
caip10Address,
99-
{
100-
pci,
101-
userOp: {
102-
...userOp,
103-
callData: userOp.callData,
104-
callGasLimit: BigInt(userOp.callGasLimit),
105-
nonce: BigInt(userOp.nonce),
106-
preVerificationGas: BigInt(userOp.preVerificationGas),
107-
verificationGasLimit: BigInt(userOp.verificationGasLimit),
108-
sender: userOp.sender,
109-
signature: userOp.signature,
110-
maxFeePerGas: BigInt(userOp.maxFeePerGas),
111-
maxPriorityFeePerGas: BigInt(userOp.maxPriorityFeePerGas),
112-
},
113-
},
114-
);
115-
console.log("Cosign response:", cosignResponse);
116-
return cosignResponse.receipt as `0x${string}`;
65+
return sendUserOpResponse.userOpId;
11766
}

0 commit comments

Comments
 (0)