Skip to content

Commit

Permalink
add support
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewkmin committed Oct 23, 2024
1 parent 6921265 commit ee8d1be
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 98 deletions.
2 changes: 0 additions & 2 deletions examples/with-zerodev-aa/.env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,5 @@ API_PRIVATE_KEY="<Turnkey API Private Key>"
BASE_URL="https://api.turnkey.com"
ORGANIZATION_ID="<Turnkey organization ID>"
SIGN_WITH="<Turnkey Wallet Account Address, Private Key Address, or Private Key ID>" # if blank, we will create a wallet for you
INFURA_KEY="<Infura API Key>"
ZERODEV_PROJECT_ID="<Zerodev Project ID>"
ZERODEV_BUNDLER_RPC="<Zerodev Bundler RPC URL>" # see https://dashboard.zerodev.app/
ZERODEV_PAYMASTER_RPC="<Zerodev Paymaster RPC URL>" # see https://dashboard.zerodev.app/
67 changes: 22 additions & 45 deletions examples/with-zerodev-aa/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Example: `with-biconomy-aa`

This example shows how to construct and broadcast a transaction using Turnkey with [`Ethers`](https://docs.ethers.org/v6/api/providers/#Signer), [`Viem`](https://viem.sh/docs/clients/wallet.html), and [`Biconomy`](https://docs.biconomy.io/account).
This example shows how to construct and broadcast a transaction using Turnkey with [`Ethers`](https://docs.ethers.org/v6/api/providers/#Signer) (WIP), [`Viem`](https://viem.sh/docs/clients/wallet.html), and [`Zerodev`](https://docs.zerodev.app/sdk/getting-started/quickstart).

If you want to see a demo with passkeys, it's coming 🔜™️!

Expand All @@ -16,7 +16,7 @@ $ cd sdk/
$ corepack enable # Install `pnpm`
$ pnpm install -r # Install dependencies
$ pnpm run build-all # Compile source code
$ cd examples/with-biconomy-aa/
$ cd examples/with-zerodev-aa/
```

### 2a/ Setting up Turnkey
Expand All @@ -27,12 +27,12 @@ The first step is to set up your Turnkey organization and account. By following
- An organization ID
- A Turnkey wallet account (address), private key address, or a private key ID

### 2b/ Setting up Biconomy
### 2b/ Setting up Zerodev

The next step is to navigate to Biconomy to create a paymaster. Visit the [Biconomy Dashboard](https://dashboard.biconomy.io/) to create a your paymaster and find the following:
The next step is to navigate to Zerodev to create an account. Visit the [Zerodev Dashboard](https://dashboard.zerodev.app/) to create a your paymaster and find the following:

- Bundler URL
- Paymaster API Key
- Bundler RPC
- Paymaster RPC

Once you've gathered these values, add them to a new `.env.local` file. Notice that your private key should be securely managed and **_never_** be committed to git.

Expand All @@ -47,13 +47,12 @@ Now open `.env.local` and add the missing environment variables:
- `BASE_URL`
- `ORGANIZATION_ID`
- `SIGN_WITH` -- a Turnkey wallet account address, private key address, or private key ID. If you leave this blank, we'll create a wallet for you.
- `INFURA_KEY` -- if this is not set, it will default to using the Community Infura key
- `BICONOMY_BUNDLER_URL`
- `BICONOMY_PAYMASTER_API_KEY`
- `ZERODEV_BUNDLER_RPC`
- `ZERODEV_PAYMASTER_RPC`

### 3/ Running the scripts

Note: there are two included — one for Viem and another for Ethers. See `package.json` for more details.
Note: there are two included — one for Viem and another for Ethers (WIP). See `package.json` for more details.

These scripts construct transactions via Turnkey and broadcast them via Infura. If the scripts exit because your account isn't funded, you can request funds on https://sepoliafaucet.com/ or https://faucet.paradigm.xyz/.

Expand All @@ -67,8 +66,9 @@ This script will do the following:

1. instantiate a Turnkey Viem wallet client
2. instantiate a Viem public client (to be used to fetch onchain data)
3. connect the wallet client to the Biconomy paymaster
4. send ETH (via type 2 EIP-1559 transaction)
3. create a Zerodev Kernel Client (with Paymaster support)
4. create a Zerodev Bundler Client
5. send ETH (via type 2 EIP-1559 transaction)

See the following for a sample output:

Expand All @@ -77,55 +77,32 @@ Network:
sepolia (chain ID 11155111)
Signer address:
0xDC608F098255C89B36da905D9132A9Ee3DD266D9
0xbcb87Df08A6a4409B28a85Af41f32Da75bD442e9
Smart wallet address:
0x7fDD1569812a168fe4B6637943BD36ec2c836A6A
0xDbf9297467030aFf40E0D9cd43D088696596B841
Balance:
0.0499994 Ether
0.0099995 Ether
Transaction count:
1
Nonce:
9
913479994650515257524606220465835134743662536739504622017003723935449093
✔ Amount to send (wei). Default to 0.0000001 ETH … 100000000000
✔ Destination address (default to TKHQ warchest) … 0x08d2b0a37F869FF76BACB5Bab3278E26ab7067B7
Sent 0.0000001 Ether to 0x08d2b0a37F869FF76BACB5Bab3278E26ab7067B7:
https://sepolia.etherscan.io/tx/0x2f2d996d6b262ebf0263b432ca3e6d621ba42d60b92344f31cf3ed94d09f49c4
https://sepolia.etherscan.io/tx/0xe70fd04de98bc47595fba282f172ff0fa75949a7b0e16647cf423e8db7fb9ed1
Bundle can be found here:
https://jiffyscan.xyz/bundle/0xe70fd04de98bc47595fba282f172ff0fa75949a7b0e16647cf423e8db7fb9ed1?network=sepolia&pageNo=0&pageSize=10
User Ops can be found here:
https://jiffyscan.xyz/bundle/0x2f2d996d6b262ebf0263b432ca3e6d621ba42d60b92344f31cf3ed94d09f49c4?network=sepolia&pageNo=0&pageSize=10
https://jiffyscan.xyz/userOpHash/0xe70fd04de98bc47595fba282f172ff0fa75949a7b0e16647cf423e8db7fb9ed1?network=sepolia&pageNo=0&pageSize=10
```

#### Ethers

```
Network:
sepolia (chain ID 11155111)
Signer address:
0xDC608F098255C89B36da905D9132A9Ee3DD266D9
Smart wallet address:
0x7fDD1569812a168fe4B6637943BD36ec2c836A6A
Balance:
0.0499993 Ether
Transaction count:
1
Nonce:
10
✔ Amount to send (wei). Default to 0.0000001 ETH … 100000000000
✔ Destination address (default to TKHQ warchest) … 0x08d2b0a37F869FF76BACB5Bab3278E26ab7067B7
Sent 0.0000001 Ether to 0x08d2b0a37F869FF76BACB5Bab3278E26ab7067B7:
https://sepolia.etherscan.io/tx/0x0f0d5346ba726f7ccf80142ae295f28bf3873b0aeb7b29488b1e3dfb949d5ba6
User Ops can be found here:
https://jiffyscan.xyz/bundle/0x0f0d5346ba726f7ccf80142ae295f28bf3873b0aeb7b29488b1e3dfb949d5ba6?network=sepolia&pageNo=0&pageSize=10
```
🚧 WIP! Come back soon🔜
3 changes: 1 addition & 2 deletions examples/with-zerodev-aa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"version": "0.1.0",
"private": true,
"scripts": {
"start-ethers": "tsx src/ethers.ts",
"start-viem": "tsx src/viem.ts",
"clean": "rimraf ./dist ./.cache",
"typecheck": "tsc --noEmit"
Expand All @@ -16,7 +15,7 @@
"@zerodev/sdk": "^5.3.22",
"dotenv": "^16.0.3",
"ethers": "^6.10.0",
"permissionless": "^0.2.10",
"permissionless": "^0.1.45",
"prompts": "^2.4.2",
"viem": "^2.18.0"
},
Expand Down
75 changes: 38 additions & 37 deletions examples/with-zerodev-aa/src/viem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,22 @@ import {
createPublicClient,
http,
type Account,
WalletClient,
formatEther,
} from "viem";
import { sepolia } from "viem/chains";

import { signerToEcdsaValidator } from "@zerodev/ecdsa-validator";
import { KERNEL_V3_1, KERNEL_V2_4 } from "@zerodev/sdk/constants";
import { KERNEL_V3_1 } from "@zerodev/sdk/constants";
import {
createKernelAccount,
createZeroDevPaymasterClient,
createKernelAccountClient,
} from "@zerodev/sdk";
import { entryPoint07Address } from "viem/account-abstraction";
import { walletClientToSmartAccountSigner } from "permissionless";
// import { toEcdsaKernelSmartAccount } from "permissionless/accounts";
// import { ENTRYPOINT_ADDRESS_V07, bundlerActions } from "permissionless";
// import { entry } from "permissionless/clients";

// import { http, createPublicClient, zeroAddress } from "viem"
// import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"
// import { sepolia } from "viem/chains"
import {
walletClientToSmartAccountSigner,
createBundlerClient,
} from "permissionless";

// Load environment variables from `.env.local`
dotenv.config({ path: path.resolve(process.cwd(), ".env.local") });
Expand All @@ -44,15 +39,13 @@ async function main() {
return;
}

const PROJECT_ID = process.env.ZERODEV_PROJECT_ID!;
const BUNDLER_RPC = process.env.ZERODEV_BUNDLER_RPC!;
const PAYMASTER_RPC = process.env.ZERODEV_PAYMASTER_RPC!;

const chain = sepolia;
// const entryPoint = ENTRYPOINT_ADDRESS_V07;
const network = "sepolia";
const entryPoint = entryPoint07Address;
// const kernelVersion = KERNEL_V3_1;
const kernelVersion = KERNEL_V2_4;
const kernelVersion = KERNEL_V3_1;

const turnkeyClient = new TurnkeyServerSDK({
apiBaseUrl: process.env.BASE_URL!,
Expand All @@ -68,25 +61,24 @@ async function main() {
signWith: process.env.SIGN_WITH!,
});

const network = "sepolia";

// Bring your own provider (such as Alchemy or Infura: https://docs.ethers.org/v6/api/providers/)
// Create Viem client for signer
const client = createWalletClient({
account: turnkeyAccount as Account,
chain: sepolia,
transport: http(BUNDLER_RPC),
});

// Create public client for fetching chain data
const publicClient = createPublicClient({
chain: sepolia,
transport: http(BUNDLER_RPC),
});

console.log("wallet client", client.account.address);
const smartAccountSigner = walletClientToSmartAccountSigner(client);

// Construct a validator
const ecdsaValidator = await signerToEcdsaValidator(publicClient, {
signer: client,
signer: smartAccountSigner,
entryPoint,
kernelVersion,
});
Expand Down Expand Up @@ -129,10 +121,7 @@ async function main() {
address: smartAccountAddress,
});

console.log("printing kernel client");
console.dir(kernelClient);

const nonce = kernelClient;
const nonce = await kernelClient.account.getNonce();
let balance =
(await publicClient.getBalance({ address: smartAccountAddress })) ?? 0;

Expand Down Expand Up @@ -179,37 +168,49 @@ async function main() {
initial: "0x08d2b0a37F869FF76BACB5Bab3278E26ab7067B7",
},
]);

const transactionRequest = {
to: destination,
value: amount,
// nonce,
// nonce: transactionCount,
type: 2,
};

// Make a simple send tx (which calls `signTransaction` under the hood)
// const userOpResponse = await smartAccountSigner?.sendTransaction(
// transactionRequest,
// {
// nonceOptions: { nonceKey: Number(0) },
// paymasterServiceData: { mode: PaymasterMode.SPONSORED },
// }
// );
const userOpHash = await kernelClient.sendUserOperation({
userOperation: {
callData: await account.encodeCallData({
to: transactionRequest.to,
value: transactionRequest.value,
data: "0x",
}),
},
});

// const { transactionHash } = await userOpResponse.waitForTxHash();
const bundlerClient = createBundlerClient({
entryPoint,
transport: http(BUNDLER_RPC),
});

const { receipt } = await bundlerClient.waitForUserOperationReceipt({
hash: userOpHash,
timeout: 60_000, // 1 minute
});

print(
`Sent ${formatEther(transactionRequest.value)} Ether to ${
transactionRequest.to
}:`,
// `https://${network}.etherscan.io/tx/${transactionHash}`
``
`https://${network}.etherscan.io/tx/${receipt.transactionHash}`
);

print(
`Bundle can be found here:`,
`https://jiffyscan.xyz/bundle/${receipt.transactionHash}?network=${network}&pageNo=0&pageSize=10`
);

print(
`User Ops can be found here:`,
// `https://jiffyscan.xyz/bundle/${transactionHash}?network=${network}&pageNo=0&pageSize=10`
``
`https://jiffyscan.xyz/userOpHash/${receipt.transactionHash}?network=${network}&pageNo=0&pageSize=10`
);
}

Expand Down
24 changes: 12 additions & 12 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ee8d1be

Please sign in to comment.