Skip to content

Commit

Permalink
Merge pull-request #113
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewkmin committed Sep 11, 2023
2 parents 0e6fb91 + cde1a5f commit 0692a52
Show file tree
Hide file tree
Showing 39 changed files with 1,234 additions and 179 deletions.
16 changes: 13 additions & 3 deletions examples/deployer/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ dotenv.config({ path: path.resolve(process.cwd(), ".env.local") });

import { TurnkeySigner } from "@turnkey/ethers";
import { ethers } from "ethers";
import { TurnkeyClient } from "@turnkey/http";
import { ApiKeyStamper } from "@turnkey/api-key-stamper";
import { createNewEthereumPrivateKey } from "./createNewEthereumPrivateKey";
import compile from "./compile";

Expand All @@ -16,11 +18,19 @@ async function main() {
return;
}

const turnkeyClient = new TurnkeyClient(
{
baseUrl: process.env.BASE_URL!,
},
new ApiKeyStamper({
apiPublicKey: process.env.API_PUBLIC_KEY!,
apiPrivateKey: process.env.API_PRIVATE_KEY!,
})
);

// Initialize a Turnkey Signer
const turnkeySigner = new TurnkeySigner({
apiPublicKey: process.env.API_PUBLIC_KEY!,
apiPrivateKey: process.env.API_PRIVATE_KEY!,
baseUrl: process.env.BASE_URL!,
client: turnkeyClient,
organizationId: process.env.ORGANIZATION_ID!,
privateKeyId: process.env.PRIVATE_KEY_ID!,
});
Expand Down
16 changes: 13 additions & 3 deletions examples/rebalancer/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import * as path from "path";
import * as dotenv from "dotenv";
import { ethers } from "ethers";
import { TurnkeySigner } from "@turnkey/ethers";
import { TurnkeyClient } from "@turnkey/http";
import { ApiKeyStamper } from "@turnkey/api-key-stamper";
import { Environment } from "./utils";

const DEFAULT_INFURA_COMMUNITY_KEY = "84842078b09946638c03157f83405213";
Expand Down Expand Up @@ -34,11 +36,19 @@ export function getTurnkeySigner(
provider: ethers.providers.Provider,
privateKeyId: string
): TurnkeySigner {
const turnkeyClient = new TurnkeyClient(
{
baseUrl: process.env.BASE_URL!,
},
new ApiKeyStamper({
apiPublicKey: process.env.API_PUBLIC_KEY!,
apiPrivateKey: process.env.API_PRIVATE_KEY!,
})
);

// Initialize a Turnkey Signer
const turnkeySigner = new TurnkeySigner({
apiPublicKey: process.env.API_PUBLIC_KEY!,
apiPrivateKey: process.env.API_PRIVATE_KEY!,
baseUrl: process.env.BASE_URL!,
client: turnkeyClient,
organizationId: process.env.ORGANIZATION_ID!,
privateKeyId,
});
Expand Down
1 change: 1 addition & 0 deletions examples/sweeper/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"dependencies": {
"@turnkey/ethers": "workspace:*",
"@turnkey/http": "workspace:*",
"@turnkey/api-key-stamper": "workspace:*",
"@uniswap/sdk-core": "^3.1.1",
"dotenv": "^16.0.3",
"ethers": "^5.7.2",
Expand Down
28 changes: 19 additions & 9 deletions examples/sweeper/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import * as path from "path";
import * as dotenv from "dotenv";
import { ethers } from "ethers";
import { TurnkeySigner } from "@turnkey/ethers";
import { TurnkeyClient } from "@turnkey/http";
import { ApiKeyStamper } from "@turnkey/api-key-stamper";
import { Environment } from "./utils";

const DEFAULT_INFURA_COMMUNITY_KEY = "84842078b09946638c03157f83405213";
Expand All @@ -28,19 +30,27 @@ export function getProvider(
return provider;
}

// Initialize a Turnkey Signer
const turnkeySigner = new TurnkeySigner({
apiPublicKey: process.env.API_PUBLIC_KEY!,
apiPrivateKey: process.env.API_PRIVATE_KEY!,
baseUrl: process.env.BASE_URL!,
organizationId: process.env.ORGANIZATION_ID!,
privateKeyId: process.env.PRIVATE_KEY_ID!,
});

// getTurnkeySigner returns a TurnkeySigner connected to the passed-in Provider
// (https://docs.ethers.org/v5/api/providers/)
export function getTurnkeySigner(
provider: ethers.providers.Provider
): TurnkeySigner {
const turnkeyClient = new TurnkeyClient(
{
baseUrl: process.env.BASE_URL!,
},
new ApiKeyStamper({
apiPublicKey: process.env.API_PUBLIC_KEY!,
apiPrivateKey: process.env.API_PRIVATE_KEY!,
})
);

// Initialize a Turnkey Signer
const turnkeySigner = new TurnkeySigner({
client: turnkeyClient,
organizationId: process.env.ORGANIZATION_ID!,
privateKeyId: process.env.PRIVATE_KEY_ID!,
});

return turnkeySigner.connect(provider);
}
22 changes: 16 additions & 6 deletions examples/trading-runner/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import * as path from "path";
import * as dotenv from "dotenv";
import { ethers } from "ethers";
import { TurnkeySigner } from "@turnkey/ethers";
import { TurnkeyClient } from "@turnkey/http";
import { ApiKeyStamper } from "@turnkey/api-key-stamper";
import { Environment } from "./utils";

const DEFAULT_INFURA_COMMUNITY_KEY = "84842078b09946638c03157f83405213";
const DEFAULT_ENV = Environment.GOERLI;
const DEFAULT_ENV = Environment.SEPOLIA;

// Load environment variables from `.env.local`
dotenv.config({ path: path.resolve(process.cwd(), ".env.local") });
Expand All @@ -16,9 +18,9 @@ let provider = new ethers.providers.InfuraProvider(
);

export function getProvider(
env = Environment.GOERLI
env = Environment.SEPOLIA
): ethers.providers.Provider {
if (env !== Environment.GOERLI) {
if (env !== Environment.SEPOLIA) {
provider = new ethers.providers.InfuraProvider(
env,
process.env.INFURA_KEY || DEFAULT_INFURA_COMMUNITY_KEY
Expand All @@ -34,11 +36,19 @@ export function getTurnkeySigner(
provider: ethers.providers.Provider,
privateKeyId: string
): TurnkeySigner {
const turnkeyClient = new TurnkeyClient(
{
baseUrl: process.env.BASE_URL!,
},
new ApiKeyStamper({
apiPublicKey: process.env.API_PUBLIC_KEY!,
apiPrivateKey: process.env.API_PRIVATE_KEY!,
})
);

// Initialize a Turnkey Signer
const turnkeySigner = new TurnkeySigner({
apiPublicKey: process.env.API_PUBLIC_KEY!,
apiPrivateKey: process.env.API_PRIVATE_KEY!,
baseUrl: process.env.BASE_URL!,
client: turnkeyClient,
organizationId: process.env.ORGANIZATION_ID!,
privateKeyId,
});
Expand Down
4 changes: 4 additions & 0 deletions examples/with-ethers-and-passkeys/.env.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
API_PUBLIC_KEY="<Turnkey API Public Key (that starts with 02 or 03)>"
API_PRIVATE_KEY="<Turnkey API Private Key>"
NEXT_PUBLIC_ORGANIZATION_ID="<Turnkey organization ID>"
NEXT_PUBLIC_TURNKEY_API_BASE_URL=https://api.turnkey.com
3 changes: 3 additions & 0 deletions examples/with-ethers-and-passkeys/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
35 changes: 35 additions & 0 deletions examples/with-ethers-and-passkeys/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
56 changes: 56 additions & 0 deletions examples/with-ethers-and-passkeys/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Example: `with-ethers-and-passkeys`

This example shows how to create sub-organizations, create private keys, and sign with the [`@turnkey/ethers`](../../packages/ethers/) signer, using passkeys.

![UI screenshot](./img/ui-screenshot.png)

The flow showcases 3 ways to make requests to Turnkey:

- the initial request to create a new [sub-organization](https://docs.turnkey.com/getting-started/sub-organizations) is authenticated in the NextJS backend with an API signature (using `API_PUBLIC_KEY`/`API_PRIVATE_KEY` from your `.env.local` file)
- the request to create a new ETH address is signed on the frontend with your passkey, but it's passed to the NextJS backend as a signed request (the body, stamp, and url are POSTed). This lets the backend submit this request on your behalf, and poll until the new "create private keys" activity completes. Once the activity completes it returns the new address to the frontend
- the request to sign a message is done 100% client-side via a Turnkey Ethers signer (see [@turnkey/ethers](../../packages/ethers/)): it's signed with your passkey, and submitted from the browser to the Turnkey API directly.

If you want to see a ethers demo with API keys instead of passkeys, head to the example [`with-ethers`](../with-ethers/).

## Getting started

### 1/ Cloning the example

Make sure you have `Node.js` installed locally; we recommend using Node v16+.

```bash
$ git clone https://github.com/tkhq/sdk
$ cd sdk/
$ corepack enable # Install `pnpm`
$ pnpm install -r # Install dependencies
$ pnpm run build-all # Compile source code
$ cd examples/with-ethers-and-passkeys/
```

### 2/ Setting up Turnkey

The first step is to set up your Turnkey organization and account. By following the [Quickstart](https://docs.turnkey.com/getting-started/quickstart) guide, you should have:

- A public/private API key pair for Turnkey
- An organization ID

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

```bash
$ cp .env.local.example .env.local
```

Now open `.env.local` and add the missing environment variables:

- `API_PUBLIC_KEY`
- `API_PRIVATE_KEY`
- `NEXT_PUBLIC_TURNKEY_API_BASE_URL`
- `NEXT_PUBLIC_ORGANIZATION_ID`

### 3/ Running the app

```bash
$ pnpm run dev
```

This command will start a NextJS app on localhost. If you navigate to http://localhost:3000 in your browser, you can follow the prompts to create a sub organization, create a private key for the newly created sub-organization, and sign a message using your passkey with a ethers custom account!
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions examples/with-ethers-and-passkeys/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};

module.exports = nextConfig;
37 changes: 37 additions & 0 deletions examples/with-ethers-and-passkeys/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "@turnkey/example-with-ethers-and-passkeys",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"typecheck": "tsc --noEmit"
},
"engines": {
"node": ">=18.0.0"
},
"dependencies": {
"@turnkey/http": "workspace:*",
"@turnkey/api-key-stamper": "workspace:*",
"@turnkey/webauthn-stamper": "workspace:*",
"@turnkey/ethers": "workspace:*",
"@types/node": "20.3.1",
"@types/react": "18.2.14",
"@types/react-dom": "18.2.6",
"axios": "^1.4.0",
"encoding": "^0.1.13",
"eslint": "8.43.0",
"eslint-config-next": "13.4.7",
"esm": "^3.2.25",
"install": "^0.13.0",
"next": "13.4.7",
"npm": "^9.7.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.45.1",
"typescript": "5.1.3",
"ethers": "^5.7.2"
}
}
25 changes: 25 additions & 0 deletions examples/with-ethers-and-passkeys/public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
29 changes: 29 additions & 0 deletions examples/with-ethers-and-passkeys/public/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions examples/with-ethers-and-passkeys/src/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
19 changes: 19 additions & 0 deletions examples/with-ethers-and-passkeys/src/pages/_document.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Document, { Html, Head, Main, NextScript } from "next/document";

class EthersPasskeysDemo extends Document {
render() {
return (
<Html>
<Head>
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}

export default EthersPasskeysDemo;
Loading

0 comments on commit 0692a52

Please sign in to comment.