-
Notifications
You must be signed in to change notification settings - Fork 537
[Docs] Add Vault SDK documentation and guides #7054
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
Changes from all commits
de300a6
f85db1f
973cd56
90ab5f0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,130 @@ | ||||||
# API Reference | ||||||
|
||||||
This section lists every exported function from **@thirdweb-dev/vault-sdk** grouped by broad capability. All functions are fully typed – hover in your editor for exact type information. | ||||||
|
||||||
--- | ||||||
|
||||||
## 1. Client utilities | ||||||
|
||||||
| Function | Description | | ||||||
| --- | --- | | ||||||
| `createVaultClient({ secretKey })` | Uses your project secret key to establish a connection to your Vault instance and returns a `VaultClient`. Create **one** client per Vault instance and reuse it. | | ||||||
| `ping({ client, request })` | Health-check endpoint mainly used in examples and tests. Returns the current server time. | | ||||||
|
||||||
```ts | ||||||
const client = await createVaultClient({ secretKey: "PROJECT_SECRET_KEY" }); | ||||||
await ping({ client, request: { message: "pong?" } }); | ||||||
``` | ||||||
|
||||||
--- | ||||||
|
||||||
## 2. Service Accounts | ||||||
|
||||||
| Function | When to use | | ||||||
| --- | --- | | ||||||
| `createServiceAccount({ request })` | Bootstrap a brand-new Vault. Returns the **admin key** and **rotation code**. _Run once during provisioning_. | | ||||||
| `getServiceAccount({ request })` | Retrieve metadata for the current service account. Requires **admin key** or a token with `serviceAccount:read` policy. | | ||||||
| `rotateServiceAccount({ request })` | Rotate (invalidate) the admin key **and** all existing access tokens in a single atomic operation. Authenticate with the **rotation code**. | | ||||||
|
||||||
Example – rotate an account after a key leak: | ||||||
|
||||||
```ts | ||||||
await rotateServiceAccount({ | ||||||
client, | ||||||
request: { | ||||||
auth: { rotationCode: process.env.VAULT_ROTATION_CODE! }, | ||||||
}, | ||||||
}); | ||||||
``` | ||||||
|
||||||
--- | ||||||
|
||||||
## 3. EOAs (Wallets) | ||||||
|
||||||
| Function | Purpose | | ||||||
| --- | --- | | ||||||
| `createEoa` | Create a new EOA (wallet) inside the Vault. Optionally attach arbitrary `metadata` for later querying. | | ||||||
| `listEoas` | Pagination-aware listing with optional metadata filters. | | ||||||
| `signTransaction` | Ask the Vault to sign an EVM transaction (legacy, 2930, 1559, 4844 or 7702). | | ||||||
| `signMessage` | Sign a plain string / hex message. | | ||||||
| `signTypedData` | Sign EIP-712 typed data with full generic type safety. | | ||||||
| `signAuthorization` | Sign an [`Authorization`](#authorization) struct used by some L2s / account-abstraction schemes. | | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
Spotted by Diamond |
||||||
| `signStructuredMessage` | Sign EIP-4337 user-operations (v0.6 & v0.7). | | ||||||
|
||||||
```ts | ||||||
// sign a 1559 tx | ||||||
import { parseTransaction, signTransaction } from "@thirdweb-dev/vault-sdk"; | ||||||
|
||||||
const tx = parseTransaction({ | ||||||
to: "0x...", | ||||||
value: 0n, | ||||||
chainId: 1, | ||||||
maxFeePerGas: 30n * 10n ** 9n, | ||||||
maxPriorityFeePerGas: 1n * 10n ** 9n, | ||||||
gasLimit: 21_000, | ||||||
}); | ||||||
|
||||||
await signTransaction({ | ||||||
client, | ||||||
request: { | ||||||
auth: { accessToken: process.env.VAULT_SIG_TOKEN! }, | ||||||
options: { from: "0xEoaAddress", transaction: tx }, | ||||||
}, | ||||||
}); | ||||||
``` | ||||||
|
||||||
> **Note**: `parseTransaction` is a convenience helper that normalises user-supplied objects – you can also build the canonical tx object yourself. | ||||||
|
||||||
--- | ||||||
|
||||||
## 4. Access Tokens | ||||||
|
||||||
| Function | Purpose | | ||||||
| --- | --- | | ||||||
| `createAccessToken` | Mint a **base token** scoped by policies & metadata. Requires **admin key**. | | ||||||
| `createSignedAccessToken` | Pure-client helper that turns a *base* token into a short-lived, signed JWT (prefixed with `vt_sat_`). No server round-trip required. | | ||||||
| `listAccessTokens` | List existing tokens with pagination and optional metadata filters. | | ||||||
| `revokeAccessToken` | Immediately invalidate a token (or all derived signed tokens) by `id`. | | ||||||
|
||||||
```ts | ||||||
// Derive a time-boxed signed token for a serverless function | ||||||
const sat = await createSignedAccessToken({ | ||||||
vaultClient: client, | ||||||
baseAccessToken: process.env.VAULT_BASE_TOKEN!, | ||||||
additionalPolicies: [ | ||||||
{ type: "eoa:signMessage", chainId: 1, messagePattern: "^0x.*" }, | ||||||
], | ||||||
expiryTimestamp: Math.floor(Date.now() / 1000) + 60 * 5, // 5 min | ||||||
}); | ||||||
``` | ||||||
|
||||||
--- | ||||||
|
||||||
## 5. Utilities | ||||||
|
||||||
| Function | Notes | | ||||||
| --- | --- | | ||||||
| `parseTransaction` | Normalises user input into a canonical `EthereumTypedTransaction` (supports Legacy, 2930, 1559, 4844, 7702). Throws `ParseTransactionError` on invalid input. | | ||||||
| `ParseTransactionError` | Custom error class thrown by the above helper. | | ||||||
|
||||||
```ts | ||||||
try { | ||||||
parseTransaction({ gas: 100_000 }); | ||||||
} catch (err) { | ||||||
if (err instanceof ParseTransactionError) { | ||||||
console.error(err.message); | ||||||
} | ||||||
} | ||||||
``` | ||||||
|
||||||
--- | ||||||
|
||||||
### Types | ||||||
|
||||||
All request & response shapes are exported as TypeScript types so you can easily model higher-level abstractions: | ||||||
|
||||||
```ts | ||||||
import type { CreateEoaPayload, SignMessagePayload, PolicyComponent } from "@thirdweb-dev/vault-sdk"; | ||||||
``` | ||||||
|
||||||
Refer to the generated `.d.ts` files for the complete list. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
# Guide – Managing Access Tokens | ||
|
||
Access tokens let you delegate finely-scoped permissions to services, cron jobs or external partners without sharing the admin key. | ||
|
||
This guide covers: | ||
|
||
1. Creating a **base** access token (server-side) | ||
2. Deriving short-lived **signed** tokens client-side | ||
3. Listing and revoking tokens | ||
|
||
--- | ||
|
||
## 1. Create a base token | ||
|
||
Base tokens are created **once** and stored securely (e.g. in your secrets manager). They cannot be scoped by expiry – instead you define *policies* that control which operations are allowed. | ||
|
||
```ts | ||
import { createVaultClient, createAccessToken } from "@thirdweb-dev/vault-sdk"; | ||
|
||
const client = await createVaultClient({ secretKey: "PROJECT_SECRET_KEY" }); | ||
|
||
const res = await createAccessToken({ | ||
client, | ||
request: { | ||
auth: { adminKey: process.env.VAULT_ADMIN_KEY! }, | ||
options: { | ||
policies: [ | ||
{ | ||
type: "eoa:signMessage", | ||
allowlist: ["0xEoaAddress"], | ||
messagePattern: "^0x.*", // only allow hex messages | ||
}, | ||
], | ||
expiresAt: new Date("2030-01-01").toISOString(), | ||
metadata: { env: "prod", owner: "backend" }, | ||
}, | ||
}, | ||
}); | ||
|
||
console.log("base token", res.data.accessToken); | ||
``` | ||
Comment on lines
+17
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Close the code fence for the base token example console.log("base token", res.data.accessToken);
+ ``` 🤖 Prompt for AI Agents
|
||
|
||
--- | ||
|
||
## 2. Create a signed access token (JWT) | ||
|
||
A **signed access token (SAT)** is a JWT created entirely on the client side. You derive it from a base token, embed additional policies and set a short expiry. | ||
|
||
```ts | ||
import { createSignedAccessToken } from "@thirdweb-dev/vault-sdk"; | ||
|
||
|
||
const sat = await createSignedAccessToken({ | ||
vaultClient: client, | ||
baseAccessToken: process.env.BASE_ACCESS_TOKEN, | ||
|
||
additionalPolicies: [ | ||
{ type: "eoa:signMessage", chainId: 1 }, | ||
], | ||
expiryTimestamp: Math.floor(Date.now() / 1000) + 300, // 5 minutes | ||
}); | ||
|
||
// Prefix: vt_sat_<JWT> | ||
console.log(sat); | ||
Comment on lines
+49
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Close the code fence for the signed access token (SAT) example console.log(sat);
+ ``` 🤖 Prompt for AI Agents
|
||
``` | ||
|
||
Send SATs to un-trusted environments (browser, serverless) – they only work until the expiry timestamp and can be revoked centrally by revoking their base token. | ||
|
||
--- | ||
|
||
## 3. List & revoke | ||
|
||
```ts | ||
import { listAccessTokens, revokeAccessToken } from "@thirdweb-dev/vault-sdk"; | ||
|
||
// List the first 10 tokens created by "backend" | ||
const list = await listAccessTokens({ | ||
client, | ||
request: { | ||
auth: { adminKey: process.env.VAULT_ADMIN_KEY! }, | ||
options: { page: 1, pageSize: 10 }, | ||
}, | ||
}); | ||
|
||
const tokenId = list.data.items[0].id; | ||
|
||
// Revoke it | ||
await revokeAccessToken({ | ||
client, | ||
request: { | ||
auth: { adminKey: process.env.VAULT_ADMIN_KEY! }, | ||
options: { id: tokenId }, | ||
}, | ||
}); | ||
``` | ||
|
||
Once revoked, **all signed tokens derived** from the base are automatically invalidated. | ||
|
||
--- | ||
|
||
### Best practices | ||
|
||
1. **Never ship base tokens to browsers** – always derive SATs. | ||
2. **Keep expiries short** (minutes) for web-apps and serverless functions. | ||
3. **Scope by metadata** to share the same policies across many EOAs. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# Guide – Creating & Managing EOAs | ||
|
||
This guide walks you through creating your first Externally Owned Account (EOA) inside the Vault and querying it later. | ||
|
||
## Prerequisites | ||
|
||
- A running Vault instance. | ||
- The **admin key** or a token with the `eoa:create` / `eoa:read` policies. | ||
- The Vault SDK installed (see Installation). | ||
|
||
--- | ||
|
||
## 1. Create a new EOA | ||
|
||
```ts | ||
import { createVaultClient, createEoa } from "@thirdweb-dev/vault-sdk"; | ||
|
||
const client = await createVaultClient({ | ||
secretKey: "PROJECT_SECRET_KEY", | ||
}); | ||
|
||
const res = await createEoa({ | ||
client, | ||
request: { | ||
auth: { adminKey: process.env.VAULT_ADMIN_KEY! }, | ||
options: { | ||
metadata: { | ||
team: "treasury", | ||
purpose: "eth-cold-storage", | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
if (!res.success) throw new Error(res.error.message); | ||
|
||
console.log("EOA address", res.data.address); | ||
``` | ||
|
||
### Metadata | ||
|
||
`metadata` accepts arbitrary key-value pairs that can later be used for filtering (`listEoas`) or for access-token policies. | ||
|
||
--- | ||
|
||
## 2. Listing EOAs | ||
|
||
```ts | ||
import { listEoas } from "@thirdweb-dev/vault-sdk"; | ||
|
||
const list = await listEoas({ | ||
client, | ||
request: { | ||
auth: { adminKey: process.env.VAULT_ADMIN_KEY! }, | ||
options: { | ||
page: 1, | ||
pageSize: 20, | ||
}, | ||
}, | ||
}); | ||
|
||
for (const eoa of list.data.items) { | ||
console.log(eoa.address, "metadata:", eoa.metadata); | ||
} | ||
``` | ||
|
||
You can build richer UIs by using the pagination data (`page`, `pageSize`, `totalRecords`). | ||
|
||
--- | ||
|
||
## 3. Best practices | ||
|
||
1. **Group wallets via metadata** – e.g. `{ env: "prod" }`, `{ team: "ops" }`. | ||
2. **Use access tokens for app-specific actions** – never ship the admin key to client-side code. | ||
3. **Rotate when you onboard/offboard admins** – see the rotation guide. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix function signature documentation in Service Accounts section.
The table lists
createServiceAccount({ request })
,getServiceAccount({ request })
, androtateServiceAccount({ request })
, but the example and actual SDK require passing{ client, request }
. Update the table entries to reflect the correct signature includingclient
.🤖 Prompt for AI Agents