Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate Quickstart Guide to use Examples from the Javascript SDK and add more context to examples #75

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/getting-started/Examples.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 3
sidebar_position: 4
description: Check out some of our example apps and use cases
slug: /getting-started/examples
---
Expand All @@ -23,7 +23,7 @@ That said, we have built out several example services and applications to help i
| [`rebalancer`](https://github.com/tkhq/sdk/tree/main/examples/rebalancer/) | A demo application which showcases an example of how to use Turnkey for managing multiple types of keys & users |
| [`sweeper`](https://github.com/tkhq/sdk/tree/main/examples/sweeper/) | Sweep funds from one address to a different address |
| [`trading-runner`](https://github.com/tkhq/sdk/tree/main/examples/trading-runner/) | A sample application demonstrating a trading operation, using various private keys, users, and policies, powered by Uniswap |
| [`wallet-export`](https://github.com/tkhq/sdk/tree/main/examples/wallet-export/) | A NextJS app that demonstrates how to use `@turnkey/iframe-stamper` to export a wallet as a mnemonic |
| [`wallet-export`](https://github.com/tkhq/sdk/tree/main/examples/wallet-export/) | A NextJS app that demonstrates how to use `@turnkey/iframe-stamper` to export a wallet as a mnemonic |
| [`with-ethers`](https://github.com/tkhq/sdk/tree/main/examples/with-ethers/) | Create a new Ethereum address, then sign and broadcast a transaction using the Ethers signer with Infura |
| [`with-viem`](https://github.com/tkhq/sdk/tree/main/examples/with-viem/) | Sign and broadcast a transaction using the Turnkey Custom Account and Infura |
| [`with-cosmjs`](https://github.com/tkhq/sdk/tree/main/examples/with-cosmjs/) | Create a new Cosmos address, then sign and broadcast a transaction on Celestia testnet using the CosmJS signer |
Expand Down Expand Up @@ -103,4 +103,4 @@ A simple example using Turnkey and Figment to easily automate ETH staking.
/>
</p>

See https://docs.figment.io/recipes/stake-eth-from-turnkey for the code.
See https://docs.figment.io/recipes/stake-eth-from-turnkey for the code.
2 changes: 1 addition & 1 deletion docs/getting-started/Organizations.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 4
sidebar_position: 5
description: Learn about Organizations on Turnkey
slug: /getting-started/organizations
---
Expand Down
189 changes: 136 additions & 53 deletions docs/getting-started/Quickstart.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: quickstart
id: quickstart-javascript
sidebar_position: 2
description: Onboard and sign your first Ethereum transaction
slug: /getting-started/quickstart
Expand All @@ -24,89 +24,172 @@ All API requests require an organization ID. Yours can be located in the user dr
style={{ width: 940 }}
/>

For convenience, it's worth setting this as a permanent shell variable:
You'll want to reference this in your code or as an environment variable, as you'll need it to make requests to the Turnkey API.

```sh
export ORGANIZATION_ID="<Your Org ID>"
```javascript
const TURNKEY_ORGANIZATION_ID = "<Your Org ID>";
```

## Add an API key
## Create an API Key

Turnkey API Keys are generic public / private key pairs that allow you to make requests to our API. To generate a new key pair, we'll use the Turnkey CLI.
Turnkey API Keys are generic public / private key pairs that allow you to make requests to our API. You can create an API Key from your user page of the dashboard. Navigate to your user page by clicking on "User Details" in the user dropdown menu, and then click "Create an API key".

#### Installing `turnkey`
<img
src="/img/quickstart/find_user_details.png"
alt="Find user details"
style={{ width: 940 }}
/>

```sh
brew install tkhq/tap/turnkey
```
<img
src="/img/quickstart/create_api_key.png"
alt="Find user details"
style={{ width: 940 }}
/>

We are employing [Homebrew](https://brew.sh/) in this guide as a quick and easy install path. For an installation path that **requires no trust in external parties**, refer to our [CLI repo](https://github.com/tkhq/tkcli).
- Select "Generate API keys in-browser" and click continue.
- Give your API key pair a name and click continue.
- Save your Public and Private Key locally.
- Make sure to click "Approve" to sign the API Creation activity with your authenticator device.

#### Generate an API key
A couple of notes:
- You will need both the public and private key to sign requests to the Turnkey API.
- **Any code using a Turnkey API private key should only ever be run server-side.**
- Every action on Turnkey will return an `activity`, including creating the API key pair in the previous step. You can read more about the [Turnkey Activity Model here](../policy-management/Policy-language.md#activity-breakdown).

```sh
turnkey generate-api-key --organization $ORGANIZATION_ID --key-name quickstart
```
## Require the Turnkey Packages

When you run this command, Turnkey’s CLI generates an API key pair and **stores the API private key locally**. Copy the `publicKey` field in the output. In the next step, we'll add this to our User.
There are two packages that you will need to make API requests to Turnkey:
1. The Turnkey HTTP library.
2. A Turnkey "stamper" library.

#### Add your public API key
The stamper library is responsible for signing a request into Turnkey, and comes in 3 different flavors:
1. `api-key-stamper` which signs requests with your Turnkey API key
2. `webauthn-stamper` which signs requests with a end-user's passkey
3. `iframe-stamper` which is a wrapper around the api-key-stamper and used specifically for Email Recovery and Email Auth

Navigate to your user page by clicking on "User Details" in the user dropdown menu.
The simplest way to get started is to use the API Key Stamper to make requests to Turnkey that are signed with the API key pair you created in the previous step.

<img
src="/img/quickstart/find_user_details.png"
alt="Find user details"
style={{ width: 940 }}
/>

Click on "Create API keys" and follow the prompts to add the generated public API key. You'll be required to authenticate with the same authenticator used during onboarding. After this succeeds, you should be all set to interact with our API.
```shell
npm install @turnkey/http
npm install @turnkey/api-key-stamper
```

NOTE: if you would like to manually your locally stored public/private API key files (e.g. `key.public`, `key.private`), you will have to save the files without newlines (which occupy extra bytes). For example, for VIM, use `:set binary noeol` or `:set binary noendofline` before writing.
## Initialize the Turnkey Client
```javascript
import { ApiKeyStamper } from '@turnkey/api-key-stamper';
import { TurnkeyClient } from '@turnkey/http';

## Create a Wallet
const TURNKEY_ORGANIZATION_ID = "<Your Org ID>";

Wallets are collections of cryptographic key pairs typically used for sending and receiving digital assets. To create one, we need to provide a name:
const stamper = new ApiKeyStamper({
apiPublicKey: "<Your Public Key>",
apiPrivateKey: "<Your Private Key>"
})

```sj
turnkey wallets create --name default --key-name quickstart
const turnkeyClient = new TurnkeyClient(
{
baseUrl: 'https://api.turnkey.com'
},
stamper
);
```

## Create an Ethereum account
## Create a Wallet

A `wallet` on Turnkey represents a multi-chain seed phrase from which many individual `accounts` can be derived. An `account` represents a specific index on a derivation path and contains the blockchain address that you can send funds to and sign on-chain transactions with. You can learn more about the specifics of Turnkey wallets [here](/getting-started/wallets). The only thing a wallet needs to be initialized is a name for the wallet.

```javascript
const response = await turnkeyClient.createWallet({
organizationId: TURNKEY_ORGANIZATION_ID,
type: 'ACTIVITY_TYPE_CREATE_WALLET',
timestampMs: String(Date.now()),
parameters: {
walletName: "Test Wallet 1",
accounts: []
}
})

To create a cryptographic key pair on our new Wallet, we need to pass our desired address format:
const walletId = response.activity.result.createWalletResult.walletId;
```

```sh
turnkey wallets accounts create --wallet default --address-format ADDRESS_FORMAT_ETHEREUM --key-name quickstart
## Create an Ethereum Account

Once a `wallet` has been created, `accounts` can be created against that `wallet` by passing in the derivation path information for any `accounts` that you want to derive. In this example we will derive Ethereum accounts, using the standard BIP44 Path format. The final number at the end of the path string represents the index in the derivation path that you want to derive the account for.

Note: If desired, you can also create `accounts` in the same API call where you create the `wallet` by passing in the account derivation paths as parameters to the `createWallet` call.

```javascript
await client.createWalletAccounts({
organizationId: TURNKEY_ORGANIZATION_ID,
type: 'ACTIVITY_TYPE_CREATE_WALLET_ACCOUNTS',
timestampMs: String(Date.now()),
parameters: {
walletId: "<Your wallet id>",
accounts: [
{
path: "m/44'/60'/0'/0/0", // account at index 0
pathFormat: "PATH_FORMAT_BIP32",
curve: "CURVE_SECP256K1",
addressFormat: "ADDRESS_FORMAT_ETHEREUM"
},
{
path: "m/44'/60'/0'/0/1", // account at index 1
pathFormat: "PATH_FORMAT_BIP32",
curve: "CURVE_SECP256K1",
addressFormat: "ADDRESS_FORMAT_ETHEREUM"
},
{
path: "m/44'/60'/0'/0/2", // account at index 2
pathFormat: "PATH_FORMAT_BIP32",
curve: "CURVE_SECP256K1",
addressFormat: "ADDRESS_FORMAT_ETHEREUM"
},
]
}
})
```

This command will produce an Ethereum address (e.g. `0x08cb1216C95149DF66978b574E484869512CE2bF`) that we'll need to sign a transaction. You can see your new Wallet account with:
You can view the created accounts and their associated Ethereum addresses with

```sh
turnkey wallets accounts list --wallet default --key-name quickstart
```javascript
await client.getWalletAccounts({
organizationId: TURNKEY_ORGANIZATION_ID,
walletId: "<Your wallet id>"
})
```

## Sign a Transaction

Now you can sign an Ethereum transaction with this new address with our [`sign_transaction` endpoint](https://docs.turnkey.com/api#tag/Signers/operation/SignTransaction). Make sure to replace the `unsignedTransaction` below with your own. You can use our [simple transaction generator](https://build.tx.xyz) if you need a quick transaction for testing:

```sh
turnkey request --path /public/v1/submit/sign_transaction --body '{
"timestampMs": "'"$(date +%s)"'000",
"type": "ACTIVITY_TYPE_SIGN_TRANSACTION_V2",
"organizationId": "'"$ORGANIZATION_ID"'",
"parameters": {
"type": "TRANSACTION_TYPE_ETHEREUM",
"signWith": "<Your Ethereum address>",
"unsignedTransaction": "<Your Transaction>"
}
}' --key-name quickstart
Once you have an account, you can sign a transaction with the account as follows.

```javascript
await turnkeyClient.signTransaction({
organizationId: TURNKEY_ORGANIZATION_ID,
type: "ACTIVITY_TYPE_SIGN_TRANSACTION_V2",
timestampMs: String(Date.now()),
parameters: {
signWith: "<Your ethereum address>" // i.e. 0x780ed9b6BF99908106d1bAA25b7658a80ADB5f42
unsignedTransaction: "<Your unsigned transaction>", // i.e. 02eb018084db4f550d850bb6338fa88252089470a8a81613dd06dc243de94ebdf861ff5f82b361831e848080c0
type: "TRANSACTION_TYPE_ETHEREUM"
}
})
```

Make sure to replace the `unsignedTransaction` below with your own. You can use our [simple transaction generator](https://build.tx.xyz) if you need a quick transaction for testing.

If you'd like to broadcast your transaction, you can easily do so via [Etherscan](https://etherscan.io/pushTx).


## Using the Webauthn Stamper

The previous actions all had to be signed server-side in our code using a Turnkey API key, but you can also have individual end-users sign Turnkey activities using their own passkeys using the webauthn stamper library. You can learn more about the specifics of the passkey implementation in the [Passkey guide](../passkeys/introduction). You can also see an example of having an end-user sign a request with a passkey in our public [Demo Passkey Wallet](https://github.com/tkhq/demo-passkey-wallet) repository.

## Best Practices (Using Sub-Organizations)

Due to cryptographic limitations of how much data can be signed at once, generally speaking, a common pattern is to create sub-organizations for each individual user, instead of creating wallets for each user directly on the parent organization. You can read more about how to properly do this in the [Suborganization Guide](../integration-guides/sub-organizations-as-wallets.md).

## Next Steps

- Check out our [examples](/getting-started/examples) to see what can be built
- Learn more about [Organizations](/getting-started/organizations) and [Wallets](/getting-started/wallets)
- See our [API design](/api-introduction) or dive into our [API reference](/api)
- Check out our [examples](/getting-started/examples) to see what can be built.
- Learn more about [Organizations](/getting-started/organizations) and [Wallets](/getting-started/wallets).
- See our [API design](/api-introduction) or dive into our [API reference](/api).
8 changes: 4 additions & 4 deletions docs/getting-started/Sub-Organizations.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 4
sidebar_position: 5
description: Learn about sub-orgs and how you can use them
slug: /getting-started/sub-organizations
---
Expand All @@ -9,15 +9,15 @@ Using Turnkey’s flexible infrastructure, you can programmatically create and m

We envision sub-organizations being very useful to model your End-Users if you're a business using Turnkey for key management. Let's explore how.

## Creating Sub-Organizations
## Creating Sub-Organizations

Creating a new sub-organization is an activity performed by the parent organization. The activity itself takes the following attributes as inputs:
Creating a new sub-organization is an activity performed by the parent organization. The activity itself takes the following attributes as inputs:
- organization name
- a list of root users
- a root quorum threshold
- [optional] a wallet (note: in versions prior to V4, this was a private key)

Root users can be programmatic or human, with one or many credentials attached.
Root users can be programmatic or human, with one or many credentials attached.

## Using Sub-Organizations

Expand Down
Loading