diff --git a/apps/portal/redirects.mjs b/apps/portal/redirects.mjs
index 97e4a221ac8..c56b523ec89 100644
--- a/apps/portal/redirects.mjs
+++ b/apps/portal/redirects.mjs
@@ -854,6 +854,7 @@ const infrastructureRedirects = {
"/guides/engine/relayer": "/engine/features/relayer",
"/infrastructure/engine/overview": "/engine",
"/engine/features/permissions": "/engine/features/admins",
+ "/engine": "/engine/v3",
//storage
"/storage/how-storage-works": "/infrastructure/storage/how-storage-works",
diff --git a/apps/portal/src/app/Header.tsx b/apps/portal/src/app/Header.tsx
index a4eb9ddf379..551fd249562 100644
--- a/apps/portal/src/app/Header.tsx
+++ b/apps/portal/src/app/Header.tsx
@@ -45,6 +45,10 @@ const links = [
];
const toolLinks = [
+ {
+ name: "Vault",
+ href: "/vault",
+ },
{
name: "Chain List",
href: "https://thirdweb.com/chainlist",
diff --git a/apps/portal/src/app/connect/account-abstraction/gasless/engine/page.mdx b/apps/portal/src/app/connect/account-abstraction/gasless/engine/page.mdx
index 98248ba0e7f..8aa905c2a2b 100644
--- a/apps/portal/src/app/connect/account-abstraction/gasless/engine/page.mdx
+++ b/apps/portal/src/app/connect/account-abstraction/gasless/engine/page.mdx
@@ -10,7 +10,7 @@ This guide assumes you have already installed Connect SDK into your application.
-Obtain the Relayer URL using Engine. For steps on how to obtain the Relayer URL, refer to the [Engine relayer guide](/engine/features/relayers).
+Obtain the Relayer URL using Engine. For steps on how to obtain the Relayer URL, refer to the [Engine relayer guide](/engine/v2/features/relayers).
diff --git a/apps/portal/src/app/connect/pay/fees/page.mdx b/apps/portal/src/app/connect/pay/fees/page.mdx
index e0124957f29..ae93a678a0f 100644
--- a/apps/portal/src/app/connect/pay/fees/page.mdx
+++ b/apps/portal/src/app/connect/pay/fees/page.mdx
@@ -24,7 +24,6 @@ You can configure who pays the protocol fee for buy or sell transactions by spec
See full reference for [`buy`](https://portal.thirdweb.com/references/typescript/v5/buy/prepare) and [`sell`](https://portal.thirdweb.com/references/typescript/v5/sell/prepare).
-
#### Setting fees on transfers or purchase mode
You can configure who pays the protocol fee for transfers or purchase mode using the `feePayer` setting. This affects the
diff --git a/apps/portal/src/app/connect/pay/overview/page.mdx b/apps/portal/src/app/connect/pay/overview/page.mdx
index 7d71ce33785..44e52b7f8a7 100644
--- a/apps/portal/src/app/connect/pay/overview/page.mdx
+++ b/apps/portal/src/app/connect/pay/overview/page.mdx
@@ -1,7 +1,7 @@
import { createMetadata, DocImage, Grid, SDKCard, FeatureCard } from "@doc";
import PayOverviewImage from "../assets/pay-overview.png";
import SupportedChains from "../../../_images/supported-chains.png";
-import {Rocket, ArrowLeftRight, Wallet, Pencil, ShieldCheck, PiggyBank, Globe, Component} from "lucide-react";
+import {RocketIcon, ArrowLeftRightIcon, WalletIcon, PencilIcon, ShieldCheckIcon, PiggyBankIcon, GlobeIcon, ComponentIcon} from "lucide-react";
export const metadata = createMetadata({
image: {
@@ -27,45 +27,45 @@ Universal Bridge allows you to create both simple and advanced payment flows for
}
+ iconUrl={}
/>
- }
- />
- }
- />
- }
- />
- }
- />
-
- }
- />
- }
- />
- }
- />
+ }
+ />
+ }
+ />
+ }
+ />
+ }
+ />
+
+ }
+ />
+ }
+ />
+ }
+ />
diff --git a/apps/portal/src/app/contracts/page.mdx b/apps/portal/src/app/contracts/page.mdx
index 27ed37067e1..5f5db26745c 100644
--- a/apps/portal/src/app/contracts/page.mdx
+++ b/apps/portal/src/app/contracts/page.mdx
@@ -1,6 +1,6 @@
import { GithubTemplateCard, ExpandableGrid, createMetadata, OpenSourceCard, DocImage, ArticleIconCard, Grid } from "@doc";
import SupportedChains from "../_images/supported-chains.png";
-import { ExternalLink } from "lucide-react";
+import { ExternalLinkIcon } from "lucide-react";
export const metadata = createMetadata({
title: "thirdweb Contracts",
@@ -16,20 +16,20 @@ Contracts is an end-to-end development suite which provides tools to develop, de
diff --git a/apps/portal/src/app/engine/features/backend-wallets/page.mdx b/apps/portal/src/app/engine/features/backend-wallets/page.mdx
deleted file mode 100644
index bccd44d247a..00000000000
--- a/apps/portal/src/app/engine/features/backend-wallets/page.mdx
+++ /dev/null
@@ -1,232 +0,0 @@
-import { createMetadata, Details } from "@doc";
-import { Callout } from "@doc";
-
-export const metadata = createMetadata({
- title: "Backend Wallets | thirdweb Engine",
- description:
- "Engine performs blockchain actions using backend wallets that you own and manage.",
-});
-
-# Backend Wallets
-
-Engine performs blockchain actions using backend wallets that you own and manage.
-
-There are multiple options for securing backend wallets.
-
-## Smart Backend Wallets
-
-Smart backend wallets are the recommended way to perform blockchain operations with Engine. Each smart backend wallet consists of an EOA (managed internally by Engine) and a smart account (using thirdweb's default account implementation).
-
-### Benefits
-
-Smart backend wallets inherit smart account benefits and offer several advantages over traditional EOAs:
-
-- **Gas Management**: Built-in paymaster eliminates the need to maintain gas tokens. This means you never need to hold crypto or top up gas.
-- **Better Nonce Management**: Smart accounts use multi-dimensional nonces, which are more efficient than EOAs.
-- **Simple Integration**: Works with all existing Engine endpoints without any code changes.
-
-### How it works
-
-The smart account is automatically deployed the first time you send a transaction on a chain. You don't need to think about deploying or managing the smart account - Engine handles everything behind the scenes. All transactions are sent as UserOperations to the EntryPoint contract on chain.
-
-
- Unlike the [previous account abstraction implementation in
- Engine](account-abstraction) where you had to manage both the account address
- (`x-account-address`) and the backend wallet address
- (`x-backend-wallet-address`) separately, smart backend wallets simplify this.
- The backend wallet address is now the smart account address itself.
-
-
-
- At this time, Smart Backend Wallets do not allow for importing a smart
- account. In use cases where you need to import a smart account (such as with
- session keys), you should use [Engine AA features that utilise the
- `x-account-address` header](account-abstraction).
-
-
-### Configuration Types
-
-- `smart:local` - Smart account backed by a local key
-- `smart:aws-kms` - Smart account backed by AWS KMS
-- `smart:gcp-kms` - Smart account backed by Google Cloud KMS
-- `smart:circle` - Smart account backed by Circle Developer-Controlled Wallets
-
-For AWS and Google Cloud KMS options, follow the setup instructions in the respective sections below.
-
-### Pricing
-
-Smart backend wallets have no additional costs to use with your Engine instance. Transactions sent from smart backend wallets follow the [same billing model as regular account abstraction transactions with thirdweb](/connect/account-abstraction/infrastructure#pricing--billing).
-Smart accounts need to be deployed on each chain. This costs gas and is billed to your account like any other transaction.
-
-## Local wallet
-
-A local wallet is a wallet created or imported from a private key. Ensure your private key is backed up before transacting with a local wallet in a production environment.
-
-> Local wallets private keys are stored encrypted in Engine's database. For security reasons, private keys cannot be exported.
-
-## AWS KMS wallet
-
-An AWS KMS Wallet is a wallet securely stored in your AWS account. Engine can create and transact with the wallet, but not delete it.
-
-
-#### Setup
-
-1. [Create an IAM user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html#id_users_create_console) with programmatic access.
-1. [Grant the following KMS permissions](https://docs.aws.amazon.com/kms/latest/developerguide/control-access.html) to this user.
- - `kms:CreateKey`
- - `kms:GetPublicKey`
- - `kms:Sign`
- - `kms:CreateAlias`
- - `kms:Verify`
-1. On the user page, navigate to **Security credentials > Access keys**.
-1. Select **Create access key** to get an **Access Key** and **Secret Key**.
-1. In the dashboard, navigate to **Configuration > Backend Wallets**.
-1. Select **AWS KMS** and provide the following:
- - Access Key (example: `AKIA...`)
- - Secret Key (example: `UW7A...`)
- - Region (example: `us-west-1`)
-
-#### Import an existing wallet
-
-1. Ensure your [KMS key is created](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html) with the following settings:
- - Key type: `Asymmetric`
- - Key spec: `ECC_SECG_P256K1`
- - Key usage: `Sign and verify`
-1. In the dashboard, navigate to **Overview > Backend Wallets**.
-1. Select **Import** and provide the following:
- - AWS KMS Key ID (example: `0489da75-9830-4a5a-97e3-e4a6df7775b3`)
- - AWS KMS ARN (example: `arn:aws:kms:us-west-1:632186309261:key/0489da75-9830-4a5a-97e3-e4a6df7775b3`)
-
-## Google Cloud KMS wallet
-
-#### Setup
-
-1. [Enable Google KMS API](https://cloud.google.com/kms/docs/create-encryption-keys#before-you-begin) for your GCP account.
-1. [Create a Service Account](https://cloud.google.com/iam/docs/service-accounts-create).
-1. Navigate to the [IAM](https://console.cloud.google.com/iam-admin/iam) page. Find the service account and select **Edit Principal** to add the following roles:
- - Cloud KMS Admin
- - Cloud KMS CryptoKey Signer/Verifier
-1. Navigate to the [Service Accounts](https://console.cloud.google.com/iam-admin/serviceaccounts) page. Select the above service account.
-1. Navigate to the **Keys** tab. Select **Add Key > Create new key**.
-1. Select **JSON** to download the JSON file. This file contains the key's private key in plaintext.
-1. In the dashboard, navigate to **Configuration > Backend Wallets**.
-1. Select **Google KMS** and provide the following:
-
-
-
- This is the Project ID of the GCP project where the key was created.
-
- **Where to find**:
-
- - Navigate to the Google Cloud Console.
- - Click on the project dropdown at the top of the page.
- - The Project ID is displayed under your project's name.
-
-
-
-
-
- This is the location where the keyring was created (e.g., us-central1, europe-west1).
-
- **Where to find**:
-
- - In the Google Cloud Console, go to **Security > Cryptographic Keys**.
- - Click on the keyring that contains your key.
- - The location is displayed in the Location field.
-
-
-
-
-
- This is the ID of the keyring where your key is stored.
-
- **Where to find**:
-
- - In the Google Cloud Console, go to **Security > Cryptographic Keys**.
- - Select the keyring that contains your key.
- - The KeyRing ID is displayed in the list or the URL.
-
-
-
-
-
- This is the email associated with the service account used for accessing the KMS key.
-
- **Where to find**:
-
- - In the Google Cloud Console, go to **IAM & Admin > Service Accounts**.
- - Find the service account you are using. its email will be in the format: `name@project.iam.gserviceaccount.com`
-
-
-
-
-
- This is the private key of the service account that is used for authenticating API requests.
-
- **Where to find**:
-
- - Open the JSON file downloaded above.
- - Copy the value of the `private_key` field.
-
-
-
-#### Import an existing wallet
-
-1. Ensure your [keyring is created](https://cloud.google.com/kms/docs/create-key-ring) with the following settings:
- - Purpose: `Asymmetric sign`
- - Algorithm: `Elliptic Curve P-256 - SHA256 Digest`
-1. In the dashboard, navigate to **Overview > Backend Wallets**.
-1. Select **Import** and provide the following:
- - GCP KMS Key ID (example: `0489da75-9830-4a5a-97e3-e4a6df7775b3`)
- - GCP KMS Version ID (example: `1`)
-
-## Circle Wallet
-
-[Circle Programmable Wallets](https://developers.circle.com/w3s/programmable-wallets) is a Wallet as a Service (WaaS) solution designed to simplify the creation and management of secure Web3 wallets and their private keys. Engine can create and transact with the wallet, but not delete it.
-
-#### Setup
-
-1. Create a Circle account at the [Circle Console](https://console.circle.com/signin).
-2. Navigate to [API & Client Keys](https://console.circle.com/api-keys).
-3. Create an API Key. (Either a standard key or a restricted key scoped to "Programmable Wallets" is required.) Do not enable the IP Allowlist. Store this key, it is not shown again.
-4. In the dashboard, navigate to **Configuration > Backend Wallets**.
-5. Select **Circle** and provide the following:
- - API Key (example: `API_KEY:...`)
-
-
- Circle API Keys are scoped to either Testnet or Mainnet. Backend wallets
- created with a testnet key will not work on the mainnet, and vice versa
- If you want to change between testnet and mainnet, you will need to
- update the API key configuration in engine, and recreate a wallet with the
- Mainnet scope.
-
-
-## Create a wallet
-
-For AWS or Google Cloud KMS wallets, you must provide your credentials.
-
-1. In the dashboard, navigate to **Overview > Backend Wallets**.
-1. Select **Create**.
-1. (Optional) Provide a label to organize your wallets.
-
-Circle wallets require creating a [Credential](/engine/features/wallet-credentials) first before creating a wallet.
-
-## Import a wallet
-
-For AWS or Google Cloud KMS wallets, you must provide your credentials.
-
-1. In the dashboard, navigate to **Overview > Backend Wallets**.
-1. Select **Import**.
-1. Provide the requested fields.
- - See above for instructions for specific wallet types.
-
-## List wallets
-
-In the dashboard, navigate to **Overview > Backend Wallets** to view your wallets created by or imported to Engine.
-
-## Best practices
-
-- It is recommend to use AWS or Google Cloud KMS wallets for production use. Private keys are never exposed and the wallet is backed up securely by the cloud provider.
-- Use labels and multiple backend wallets to organize and track usage.
- - Example: Use one wallet to pay out creators on your platform and another to airdrop NFTs to users.
-- If your wallets require topping up gas or ERC20 tokens regularly, consider a separate "funds storage" backend wallet that transfers funds to other wallets via the dashboard UI or API.
diff --git a/apps/portal/src/app/engine/page.mdx b/apps/portal/src/app/engine/page.mdx
deleted file mode 100644
index 6bf9f717ea0..00000000000
--- a/apps/portal/src/app/engine/page.mdx
+++ /dev/null
@@ -1,92 +0,0 @@
-import OverviewImage from "./assets/engine-overview.png";
-import { DocImage, OpenSourceCard } from "@doc";
-import { createMetadata } from "@/components/Document";
-
-export const metadata = createMetadata({
- title: "thirdweb Engine",
- description: "An open-source, backend server that reads, writes, and deploys contracts at production scale.",
-});
-
-# Engine
-
-Engine is an open-source, backend server that reads, writes, and deploys contracts at production scale.
-
-## Why use Engine?
-
-Engine enables your app to:
-
-- Send multiple blockchain transactions at once.
-- Resubmit stuck transactions, handling nonce values, gas settings, and RPC errors.
-- Avoid duplicate transactions.
-- Manage multiple backend wallets and their funds.
-- Control access from your backends and team members.
-- Sponsor user gas fees.
-- Deploy and interact with smart accounts.
-- Subscribe to contract events and transactions.
-
-🚀 [Get Engine hosted by thirdweb](https://thirdweb.com/team/~/~/engine/create) or [self-host for free](/engine/self-host).
-
-### Tiers
-
-Engine is available in two tiers: Cloud and Dedicated.
-- **Cloud**: thirdweb-hosted Engine with autoscaling and high availability.
-- **Dedicated**: Self-hosted Engine with full control over your infrastructure.
-
-
-
-
-
-
-## Standard Engine
-
-Supports 500 write transactions per second. Great for minting APIs, airdrops, and managing user wallets.
-
-#### Features
-
-- High transaction throughput - Transactions batched on the same
- block with nonces managed automatically.
-- Secure backend wallets - Your backend wallets stored locally,
- on AWS KMS, or on Google KMS.
-- Any contract on any EVM chain - Supports contract calls on all
- 1700+ EVM blockchains
- and private subnets.
-- Contract deployments - Deploy smart accounts, tokens, NFTs, marketplaces,
- and more.
-- Account abstraction - Use smart accounts and session keys to transact
- on behalf of your users.
-- Built-in relayer - Sponsor gas for your users so reduce user friction.
-- Event webhooks - Get notified of wallet and contract events to
- automate other actions like payments or emails.
-- Contract subscriptions - Store event logs and transaction receipts
- to be queried later.
-- Transaction observability - Debug transaction failures with detailed
- timelines, onchain errors, and gas details.
-- Idempotency - Prevent costly, duplicate transactions.
-- Production-ready web3 infrastructure - Includes RPC, IPFS, and
- Account Abstraction out of the box.
-
-## Premium Engine
-
-Engine Premium provides added scaling and resilience. It include server autoscaling, server failover, database failover, and 30-day database backups.
-
-#### Features
-
-- **_Everything in Standard Engine_**
-- **Autoscaling** - Scale to millions of users with a fleet of Engine instances that scale up along with your traffic.
-- **Production-grade Server** - High availability and redundancy.
-- **Production-grade Database** - High availability, Multi-AZ.
-- **Database backups** - Recoverability and peace of mind for your stored data (30-day database backups).
-
-## Pricing
-
-Cloud-hosting Engine with thirdweb starts at $99 per month. Learn more about [Engine pricing](https://thirdweb.com/team/~/~/engine/create).
-
-Self-hosting Engine is always free.
-
-## Get in touch
-
-For dedicated support and feature requests, [contact Sales](https://thirdweb.com/contact-us).
diff --git a/apps/portal/src/app/engine/production-checklist/page.mdx b/apps/portal/src/app/engine/production-checklist/page.mdx
deleted file mode 100644
index a3608d8f1cb..00000000000
--- a/apps/portal/src/app/engine/production-checklist/page.mdx
+++ /dev/null
@@ -1,18 +0,0 @@
-# Production Checklist
-
-Follow best practices when using Engine in a production environment.
-
-### Security
-
-- The Engine API is intended to be called from your backend only. Ensure your access tokens are not accessible from your frontend.
- - Exception: Relayer endpoints do not require access tokens. [Learn more about relayers.](infrastructure/engine/guides/relayer)
-- Securely store access tokens and the thirdweb secret key. Rotate these credentials if they are compromised.
-- Use labels to keep track of your wallets, admins, and access tokens.
-- Use access token with expirations to grant time-bound access.
-- Regularly review the admins list to remove inactive and former team members.
-
-### Backend wallets
-
-- Recommended: Use a wallet backed by AWS KMS or Google KMS. Wallet access is always recoverable and private keys are never exposed.
-- If using a local wallet: **back up the private key**. Engine cannot recover private keys if the encrypted stored data is lost or corrupted.
-- Ensure your backend wallets have sufficient funds. Use [wallet webhooks](/engine/features/webhooks) to alert when your gas balance is low.
diff --git a/apps/portal/src/app/engine/assets/add-alert.png b/apps/portal/src/app/engine/v2/assets/add-alert.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/add-alert.png
rename to apps/portal/src/app/engine/v2/assets/add-alert.png
diff --git a/apps/portal/src/app/engine/assets/add-custom-chain-1.png b/apps/portal/src/app/engine/v2/assets/add-custom-chain-1.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/add-custom-chain-1.png
rename to apps/portal/src/app/engine/v2/assets/add-custom-chain-1.png
diff --git a/apps/portal/src/app/engine/assets/add-custom-chain-2.png b/apps/portal/src/app/engine/v2/assets/add-custom-chain-2.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/add-custom-chain-2.png
rename to apps/portal/src/app/engine/v2/assets/add-custom-chain-2.png
diff --git a/apps/portal/src/app/engine/assets/add-custom-chain-3.png b/apps/portal/src/app/engine/v2/assets/add-custom-chain-3.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/add-custom-chain-3.png
rename to apps/portal/src/app/engine/v2/assets/add-custom-chain-3.png
diff --git a/apps/portal/src/app/engine/assets/add-custom-chain-4.png b/apps/portal/src/app/engine/v2/assets/add-custom-chain-4.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/add-custom-chain-4.png
rename to apps/portal/src/app/engine/v2/assets/add-custom-chain-4.png
diff --git a/apps/portal/src/app/engine/assets/airdrop-nfts-1.png b/apps/portal/src/app/engine/v2/assets/airdrop-nfts-1.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/airdrop-nfts-1.png
rename to apps/portal/src/app/engine/v2/assets/airdrop-nfts-1.png
diff --git a/apps/portal/src/app/engine/assets/airdrop-nfts-2.png b/apps/portal/src/app/engine/v2/assets/airdrop-nfts-2.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/airdrop-nfts-2.png
rename to apps/portal/src/app/engine/v2/assets/airdrop-nfts-2.png
diff --git a/apps/portal/src/app/engine/assets/airdrop-nfts-3.png b/apps/portal/src/app/engine/v2/assets/airdrop-nfts-3.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/airdrop-nfts-3.png
rename to apps/portal/src/app/engine/v2/assets/airdrop-nfts-3.png
diff --git a/apps/portal/src/app/engine/assets/airdrop-nfts-4.png b/apps/portal/src/app/engine/v2/assets/airdrop-nfts-4.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/airdrop-nfts-4.png
rename to apps/portal/src/app/engine/v2/assets/airdrop-nfts-4.png
diff --git a/apps/portal/src/app/engine/assets/airdrop-overview.png b/apps/portal/src/app/engine/v2/assets/airdrop-overview.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/airdrop-overview.png
rename to apps/portal/src/app/engine/v2/assets/airdrop-overview.png
diff --git a/apps/portal/src/app/engine/assets/authorize-api.png b/apps/portal/src/app/engine/v2/assets/authorize-api.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/authorize-api.png
rename to apps/portal/src/app/engine/v2/assets/authorize-api.png
diff --git a/apps/portal/src/app/engine/assets/authorize-bearer.png b/apps/portal/src/app/engine/v2/assets/authorize-bearer.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/authorize-bearer.png
rename to apps/portal/src/app/engine/v2/assets/authorize-bearer.png
diff --git a/apps/portal/src/app/engine/assets/cancel-transaction-button.png b/apps/portal/src/app/engine/v2/assets/cancel-transaction-button.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/cancel-transaction-button.png
rename to apps/portal/src/app/engine/v2/assets/cancel-transaction-button.png
diff --git a/apps/portal/src/app/engine/assets/engine-docs-diagram-updated.svg b/apps/portal/src/app/engine/v2/assets/engine-docs-diagram-updated.svg
similarity index 100%
rename from apps/portal/src/app/engine/assets/engine-docs-diagram-updated.svg
rename to apps/portal/src/app/engine/v2/assets/engine-docs-diagram-updated.svg
diff --git a/apps/portal/src/app/engine/assets/engine-out-of-gas.png b/apps/portal/src/app/engine/v2/assets/engine-out-of-gas.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/engine-out-of-gas.png
rename to apps/portal/src/app/engine/v2/assets/engine-out-of-gas.png
diff --git a/apps/portal/src/app/engine/assets/engine-overview.png b/apps/portal/src/app/engine/v2/assets/engine-overview.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/engine-overview.png
rename to apps/portal/src/app/engine/v2/assets/engine-overview.png
diff --git a/apps/portal/src/app/engine/assets/engine-webhooks.webp b/apps/portal/src/app/engine/v2/assets/engine-webhooks.webp
similarity index 100%
rename from apps/portal/src/app/engine/assets/engine-webhooks.webp
rename to apps/portal/src/app/engine/v2/assets/engine-webhooks.webp
diff --git a/apps/portal/src/app/engine/assets/nft-checkout-1.png b/apps/portal/src/app/engine/v2/assets/nft-checkout-1.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/nft-checkout-1.png
rename to apps/portal/src/app/engine/v2/assets/nft-checkout-1.png
diff --git a/apps/portal/src/app/engine/assets/nft-checkout-2.png b/apps/portal/src/app/engine/v2/assets/nft-checkout-2.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/nft-checkout-2.png
rename to apps/portal/src/app/engine/v2/assets/nft-checkout-2.png
diff --git a/apps/portal/src/app/engine/assets/nft-checkout-3.png b/apps/portal/src/app/engine/v2/assets/nft-checkout-3.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/nft-checkout-3.png
rename to apps/portal/src/app/engine/v2/assets/nft-checkout-3.png
diff --git a/apps/portal/src/app/engine/assets/nft-checkout-overview.png b/apps/portal/src/app/engine/v2/assets/nft-checkout-overview.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/nft-checkout-overview.png
rename to apps/portal/src/app/engine/v2/assets/nft-checkout-overview.png
diff --git a/apps/portal/src/app/engine/assets/recent-alerts.png b/apps/portal/src/app/engine/v2/assets/recent-alerts.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/recent-alerts.png
rename to apps/portal/src/app/engine/v2/assets/recent-alerts.png
diff --git a/apps/portal/src/app/engine/assets/relayer-1.png b/apps/portal/src/app/engine/v2/assets/relayer-1.png
similarity index 100%
rename from apps/portal/src/app/engine/assets/relayer-1.png
rename to apps/portal/src/app/engine/v2/assets/relayer-1.png
diff --git a/apps/portal/src/app/engine/assets/tx-lifecycle.webp b/apps/portal/src/app/engine/v2/assets/tx-lifecycle.webp
similarity index 100%
rename from apps/portal/src/app/engine/assets/tx-lifecycle.webp
rename to apps/portal/src/app/engine/v2/assets/tx-lifecycle.webp
diff --git a/apps/portal/src/app/engine/v2/configure-wallets/aws-kms/page.mdx b/apps/portal/src/app/engine/v2/configure-wallets/aws-kms/page.mdx
new file mode 100644
index 00000000000..5581924f7f2
--- /dev/null
+++ b/apps/portal/src/app/engine/v2/configure-wallets/aws-kms/page.mdx
@@ -0,0 +1,45 @@
+import { Callout } from '@doc';
+
+export const metadata = {
+ title: "AWS KMS Wallet",
+ description:
+ "Learn how to set up an AWS KMS wallet with thirdweb Engine.",
+};
+
+
+## AWS KMS wallet
+
+An AWS KMS Wallet is a wallet securely stored in your AWS account. Engine can create and transact with the wallet, but not delete it.
+
+
+ AWS KMS wallets are not currently supported on Engine Cloud. They are currently supported on Engine Dedicated v2, and will be available soon with Dedicated v3.
+
+
+
+#### Setup
+
+1. [Create an IAM user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html#id_users_create_console) with programmatic access.
+1. [Grant the following KMS permissions](https://docs.aws.amazon.com/kms/latest/developerguide/control-access.html) to this user.
+ - `kms:CreateKey`
+ - `kms:GetPublicKey`
+ - `kms:Sign`
+ - `kms:CreateAlias`
+ - `kms:Verify`
+1. On the user page, navigate to **Security credentials > Access keys**.
+1. Select **Create access key** to get an **Access Key** and **Secret Key**.
+1. In the dashboard, navigate to **Configuration > Server Wallets**.
+1. Select **AWS KMS** and provide the following:
+ - Access Key (example: `AKIA...`)
+ - Secret Key (example: `UW7A...`)
+ - Region (example: `us-west-1`)
+
+#### Import an existing wallet
+
+1. Ensure your [KMS key is created](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html) with the following settings:
+ - Key type: `Asymmetric`
+ - Key spec: `ECC_SECG_P256K1`
+ - Key usage: `Sign and verify`
+1. In the dashboard, navigate to **Overview > Server Wallets**.
+1. Select **Import** and provide the following:
+ - AWS KMS Key ID (example: `0489da75-9830-4a5a-97e3-e4a6df7775b3`)
+ - AWS KMS ARN (example: `arn:aws:kms:us-west-1:632186309261:key/0489da75-9830-4a5a-97e3-e4a6df7775b3`)
\ No newline at end of file
diff --git a/apps/portal/src/app/engine/v2/configure-wallets/circle-wallet/page.mdx b/apps/portal/src/app/engine/v2/configure-wallets/circle-wallet/page.mdx
new file mode 100644
index 00000000000..f9e3087151c
--- /dev/null
+++ b/apps/portal/src/app/engine/v2/configure-wallets/circle-wallet/page.mdx
@@ -0,0 +1,32 @@
+import { Callout } from '@doc';
+
+export const metadata = {
+ title: "Circle Wallet",
+ description:
+ "Learn how to set up a Circle wallet with thirdweb Engine.",
+};
+
+## Circle Wallet
+
+[Circle Programmable Wallets](https://developers.circle.com/w3s/programmable-wallets) is a Wallet as a Service (WaaS) solution designed to simplify the creation and management of secure Web3 wallets and their private keys. Engine can create and transact with the wallet, but not delete it.
+
+
+ Circle wallets are not currently supported on Engine Cloud. They are currently supported on Engine Dedicated v2, and will be available soon with Dedicated v3.
+
+
+#### Setup
+
+1. Create a Circle account at the [Circle Console](https://console.circle.com/signin).
+2. Navigate to [API & Client Keys](https://console.circle.com/api-keys).
+3. Create an API Key. (Either a standard key or a restricted key scoped to "Programmable Wallets" is required.) Do not enable the IP Allowlist. Store this key, it is not shown again.
+4. In the dashboard, navigate to **Configuration > Server Wallets**.
+5. Select **Circle** and provide the following:
+ - API Key (example: `API_KEY:...`)
+
+
+ Circle API Keys are scoped to either Testnet or Mainnet. Server wallets
+ created with a testnet key will not work on the mainnet, and vice versa
+ If you want to change between testnet and mainnet, you will need to
+ update the API key configuration in engine, and recreate a wallet with the
+ Mainnet scope.
+
\ No newline at end of file
diff --git a/apps/portal/src/app/engine/v2/configure-wallets/gcp-kms/page.mdx b/apps/portal/src/app/engine/v2/configure-wallets/gcp-kms/page.mdx
new file mode 100644
index 00000000000..58e72dd2843
--- /dev/null
+++ b/apps/portal/src/app/engine/v2/configure-wallets/gcp-kms/page.mdx
@@ -0,0 +1,87 @@
+import { Details } from "@doc";
+
+## Google Cloud KMS wallet
+
+A Google Cloud KMS Wallet is a wallet securely stored in your Google Cloud account. Engine can create and transact with the wallet, but not delete it.
+
+#### Setup
+
+1. [Enable Google KMS API](https://cloud.google.com/kms/docs/create-encryption-keys#before-you-begin) for your GCP account.
+1. [Create a Service Account](https://cloud.google.com/iam/docs/service-accounts-create).
+1. Navigate to the [IAM](https://console.cloud.google.com/iam-admin/iam) page. Find the service account and select **Edit Principal** to add the following roles:
+ - Cloud KMS Admin
+ - Cloud KMS CryptoKey Signer/Verifier
+1. Navigate to the [Service Accounts](https://console.cloud.google.com/iam-admin/serviceaccounts) page. Select the above service account.
+1. Navigate to the **Keys** tab. Select **Add Key > Create new key**.
+1. Select **JSON** to download the JSON file. This file contains the key's private key in plaintext.
+1. In the dashboard, navigate to **Configuration > Server Wallets**.
+1. Select **Google KMS** and provide the following:
+
+
+
+ This is the Project ID of the GCP project where the key was created.
+
+ **Where to find**:
+
+ - Navigate to the Google Cloud Console.
+ - Click on the project dropdown at the top of the page.
+ - The Project ID is displayed under your project's name.
+
+
+
+
+
+ This is the location where the keyring was created (e.g., us-central1, europe-west1).
+
+ **Where to find**:
+
+ - In the Google Cloud Console, go to **Security > Cryptographic Keys**.
+ - Click on the keyring that contains your key.
+ - The location is displayed in the Location field.
+
+
+
+
+
+ This is the ID of the keyring where your key is stored.
+
+ **Where to find**:
+
+ - In the Google Cloud Console, go to **Security > Cryptographic Keys**.
+ - Select the keyring that contains your key.
+ - The KeyRing ID is displayed in the list or the URL.
+
+
+
+
+
+ This is the email associated with the service account used for accessing the KMS key.
+
+ **Where to find**:
+
+ - In the Google Cloud Console, go to **IAM & Admin > Service Accounts**.
+ - Find the service account you are using. its email will be in the format: `name@project.iam.gserviceaccount.com`
+
+
+
+
+
+ This is the private key of the service account that is used for authenticating API requests.
+
+ **Where to find**:
+
+ - Open the JSON file downloaded above.
+ - Copy the value of the `private_key` field.
+
+
+
+#### Import an existing wallet
+
+1. Ensure your [keyring is created](https://cloud.google.com/kms/docs/create-key-ring) with the following settings:
+ - Purpose: `Asymmetric sign`
+ - Algorithm: `Elliptic Curve P-256 - SHA256 Digest`
+1. In the dashboard, navigate to **Overview > Server Wallets**.
+1. Select **Import** and provide the following:
+ - GCP KMS Key ID (example: `0489da75-9830-4a5a-97e3-e4a6df7775b3`)
+ - GCP KMS Version ID (example: `1`)
+
diff --git a/apps/portal/src/app/engine/v2/configure-wallets/page.mdx b/apps/portal/src/app/engine/v2/configure-wallets/page.mdx
new file mode 100644
index 00000000000..1d7a6bed64f
--- /dev/null
+++ b/apps/portal/src/app/engine/v2/configure-wallets/page.mdx
@@ -0,0 +1,47 @@
+import { createMetadata, Callout } from "@/components/Document";
+
+export const metadata = createMetadata({
+ title: "Configure Wallets | thirdweb Engine",
+ description: "Configure your server wallets to perform blockchain actions with Engine.",
+});
+
+# Configure Engine Wallets
+
+Engine performs blockchain actions using server wallets that you own and manage.
+
+### Smart Server Wallets
+
+Smart server wallets are the **recommended option** to perform blockchain actions with Engine.
+
+**Benefits:**
+- Eliminate manual gas management. Smart server wallets are automatically funded via your thirdweb-linked payment method using a built-in paymaster.
+- Smart accounts use multi-dimensional nonces, which are more efficient than EOAs.
+- Works with all existing Engine endpoints without needing any code changes.
+- Secured non-custodially through Vault, thirdweb's key management system.
+
+Smart server wallets are included with Engine Cloud and Engine Dedicated. [Learn how to configure your own smart server wallets.](/engine/v2/configure-wallets/server-wallets)
+
+### Secure and import your own EOA
+
+For users wanting to use their own wallets, we recommend securing your wallet with a key management service such as [AWS KMS](/engine/v2/configure-wallets/aws-kms) or [Google Cloud KMS](/engine/v2/configure-wallets/gcp-kms).
+
+**Benefits:**
+- Import your own existing wallets and use them with Engine.
+
+Importing secured EOAs through AWS KMS or Google are included in the Engine Dedicated plan.
+### Circle Programmable Wallets
+
+Circle Programmable Wallets is a Wallet as a Service (WaaS) solution designed to simplify the creation and management of secure Web3 wallets and their private keys.
+
+### Configuration Types
+
+- `smart:local` - Smart account backed by a local key
+- `smart:aws-kms` - Smart account backed by AWS KMS
+- `smart:gcp-kms` - Smart account backed by Google Cloud KMS
+- `smart:circle` - Smart account backed by Circle Developer-Controlled Wallets
+
+## Best practices
+
+- Using AWS or Google Cloud KMS wallets is recommended for securing wallets for production use. Private keys are never exposed and the wallet is backed up securely by the cloud provider.
+- Use labels and multiple server wallets to organize and track usage. Example: Use one wallet to pay out creators on your platform and another to airdrop NFTs to users.
+- If using your own wallets require topping up gas or ERC20 tokens regularly, consider creating separate "funds storage" backend wallet that transfers funds to other wallets via the dashboard UI or API.
\ No newline at end of file
diff --git a/apps/portal/src/app/engine/v2/configure-wallets/server-wallet/page.mdx b/apps/portal/src/app/engine/v2/configure-wallets/server-wallet/page.mdx
new file mode 100644
index 00000000000..3e39ef82842
--- /dev/null
+++ b/apps/portal/src/app/engine/v2/configure-wallets/server-wallet/page.mdx
@@ -0,0 +1,37 @@
+import { Details } from "@doc";
+
+## Smart Server Wallets
+
+Smart server wallets are the recommended way to perform blockchain operations with Engine. Each smart server wallet consists of an EOA (managed internally by Engine) and a smart account (using thirdweb's default account implementation).
+
+### Benefits
+
+Smart server wallets inherit smart account benefits and offer several advantages over traditional EOAs:
+
+- **Gas Management**: Built-in paymaster eliminates the need to maintain gas tokens. This means you never need to hold crypto or top up gas.
+- **Better Nonce Management**: Smart accounts use multi-dimensional nonces, which are more efficient than EOAs.
+- **Simple Integration**: Works with all existing Engine endpoints without any code changes.
+
+### How it works
+
+The smart account is automatically deployed the first time you send a transaction on a chain. You don't need to think about deploying or managing the smart account - Engine handles everything behind the scenes. All transactions are sent as UserOperations to the EntryPoint contract on chain.
+
+
+ Unlike the [previous account abstraction implementation in
+ Engine](account-abstraction) where you had to manage both the account address
+ (`x-account-address`) and the backend wallet address
+ (`x-backend-wallet-address`) separately, smart backend wallets simplify this.
+ The backend wallet address is now the smart account address itself.
+
+
+
+ At this time, Smart Backend Wallets do not allow for importing a smart
+ account. In use cases where you need to import a smart account (such as with
+ session keys), you should use [Engine AA features that utilise the
+ `x-account-address` header](account-abstraction).
+
+
+### Pricing
+
+Smart server wallets have no additional costs to use with your Engine instance. Transactions sent from smart backend wallets follow the [same billing model as regular account abstraction transactions with thirdweb](/connect/account-abstraction/infrastructure#pricing--billing).
+Smart accounts need to be deployed on each chain. This costs gas and is billed to your account like any other transaction.
\ No newline at end of file
diff --git a/apps/portal/src/app/engine/features/wallet-credentials/page.mdx b/apps/portal/src/app/engine/v2/configure-wallets/wallet-credentials/page.mdx
similarity index 100%
rename from apps/portal/src/app/engine/features/wallet-credentials/page.mdx
rename to apps/portal/src/app/engine/v2/configure-wallets/wallet-credentials/page.mdx
diff --git a/apps/portal/src/app/engine/faq/page.mdx b/apps/portal/src/app/engine/v2/faq/page.mdx
similarity index 82%
rename from apps/portal/src/app/engine/faq/page.mdx
rename to apps/portal/src/app/engine/v2/faq/page.mdx
index 9c5fe941160..46fa72d0680 100644
--- a/apps/portal/src/app/engine/faq/page.mdx
+++ b/apps/portal/src/app/engine/v2/faq/page.mdx
@@ -1,20 +1,17 @@
-import { Callout } from "@doc";
+import { Callout, Details } from "@doc";
-# FAQ
-
-## About Engine
-
-### Which contracts work with Engine?
+# Engine FAQs
+
Engine supports reads and writes to any contract verified on the blockchain explorer, including any contract deployed via thirdweb.
_Note: Some endpoints allow providing the contract ABI to support any unverified contract._
Engine also supports deploys for thirdweb [prebuilt contracts](https://thirdweb.com/explore) including NFTs, tokens, marketplaces, and smart accounts.
If you have a question about a particular contract type, [contact us](https://thirdweb.com/support).
+
-### How are Engine and the thirdweb Contract SDK different?
-
+
Engine is a server that manages your backend wallets and how they interact with contracts. This difference unlocks capabilities that thirdweb and other web3 SDKs, including:
- Management of KMS backend wallets
@@ -24,16 +21,15 @@ Engine is a server that manages your backend wallets and how they interact with
- Webhooks on completed transactions to sync onchain and off-chain activity
Additionally, Engine is built on top of the thirdweb SDK and has the same capabilities.
+
-## Using Engine
-
-### How do I wait for a transaction to be mined?
+
Write calls to contracts do not block until they are mined. Instead they enqueue an async job and immediately return a reference to the job called `queueId`.
Here are three ways to determine when the job is mined:
-- Use [webhooks](/engine/features/webhooks) to notify your backend when a transaction event occurs.
+- Use [webhooks](/engine/v2/features/webhooks) to notify your backend when a transaction event occurs.
- Poll the `/transaction/status/` endpoint.
- Use websockets:
@@ -46,8 +42,9 @@ Here are three ways to determine when the job is mined:
console.log("Received data:", JSON.parse(res.result));
};
```
+
-### How do I send native currency with my transaction?
+
To send native tokens (e.g. ETH on Ethereum), set `txOverrides.value`.
This may be required when calling a `payable` contract method.
@@ -64,7 +61,9 @@ Here's an example of sending 0.2 ETH:
}
```
-### How do I override gas settings?
+
+
+
To override the gas settings, set relevant `txOverrides` gas fields.
Each field is optional and will be estimated by Engine if omitted.
@@ -89,7 +88,9 @@ Otherwise if gas prices don't fall, transactions may be in your queue indefinite
-### How do I set a timeout on transactions?
+
+
+
To specify a transaction timeout, set `txOverrides.timeoutSeconds`.
Engine flags transactions as `errored` if they are not sent before the timeout. An `errored` webhook will be sent.
@@ -106,3 +107,5 @@ Here's an example of a 2-hour timeout:
}
}
```
+
+
diff --git a/apps/portal/src/app/engine/features/access-tokens/page.mdx b/apps/portal/src/app/engine/v2/features/access-tokens/page.mdx
similarity index 91%
rename from apps/portal/src/app/engine/features/access-tokens/page.mdx
rename to apps/portal/src/app/engine/v2/features/access-tokens/page.mdx
index de1e9346b19..53ed002f9b4 100644
--- a/apps/portal/src/app/engine/features/access-tokens/page.mdx
+++ b/apps/portal/src/app/engine/v2/features/access-tokens/page.mdx
@@ -36,4 +36,4 @@ Securely store access tokens and remove them if they are compromised.
#### How do I generate short-lived access tokens?
-Consider using [Keypair Authentication](/engine/features/keypair-authentication) (advanced feature).
+Consider using [Keypair Authentication](/engine/v2/features/keypair-authentication) (advanced feature).
diff --git a/apps/portal/src/app/engine/features/account-abstraction/page.mdx b/apps/portal/src/app/engine/v2/features/account-abstraction/page.mdx
similarity index 92%
rename from apps/portal/src/app/engine/features/account-abstraction/page.mdx
rename to apps/portal/src/app/engine/v2/features/account-abstraction/page.mdx
index def918133ff..2a210151b91 100644
--- a/apps/portal/src/app/engine/features/account-abstraction/page.mdx
+++ b/apps/portal/src/app/engine/v2/features/account-abstraction/page.mdx
@@ -9,7 +9,7 @@ export const metadata = createMetadata({
# Account Abstraction
-Consider using [Smart Backend Wallets](/engine/features/backend-wallets#smart-backend-wallets) instead. They combine EOA and smart account management into a single wallet, with automatic deployment and simplified integration:
+Consider using [Smart Backend Wallets](/engine/v2/features/backend-wallets#smart-backend-wallets) instead. They combine EOA and smart account management into a single wallet, with automatic deployment and simplified integration:
- No need to deploy or manage account factories
- No separate account and backend wallet addresses to track
diff --git a/apps/portal/src/app/engine/features/admins/page.mdx b/apps/portal/src/app/engine/v2/features/admins/page.mdx
similarity index 100%
rename from apps/portal/src/app/engine/features/admins/page.mdx
rename to apps/portal/src/app/engine/v2/features/admins/page.mdx
diff --git a/apps/portal/src/app/engine/features/alert-notifications/page.mdx b/apps/portal/src/app/engine/v2/features/alert-notifications/page.mdx
similarity index 100%
rename from apps/portal/src/app/engine/features/alert-notifications/page.mdx
rename to apps/portal/src/app/engine/v2/features/alert-notifications/page.mdx
diff --git a/apps/portal/src/app/engine/v2/features/backend-wallets/page.mdx b/apps/portal/src/app/engine/v2/features/backend-wallets/page.mdx
new file mode 100644
index 00000000000..560f6a2b455
--- /dev/null
+++ b/apps/portal/src/app/engine/v2/features/backend-wallets/page.mdx
@@ -0,0 +1,28 @@
+import { createMetadata, Details } from "@doc";
+import { Callout } from "@doc";
+
+export const metadata = createMetadata({
+ title: "Server Wallets | thirdweb Engine",
+ description:
+ "Engine performs blockchain actions using server wallets that you own and manage.",
+});
+
+## Create a wallet
+
+For AWS or Google Cloud KMS wallets, you must provide your credentials.
+
+1. In the dashboard, navigate to **Overview > Server Wallets**.
+1. Select **Create**.
+1. (Optional) Provide a label to organize your wallets.
+
+Circle wallets require creating a [Credential](/engine/v2/features/wallet-credentials) first before creating a wallet.
+
+## Import a wallet
+
+For AWS or Google Cloud KMS wallets, you must provide your credentials.
+
+1. In the dashboard, navigate to **Overview > Server Wallets**.
+1. Select **Import**.
+1. Provide the requested fields.
+ - See above for instructions for specific wallet types.
+
diff --git a/apps/portal/src/app/engine/features/contract-subscriptions/page.mdx b/apps/portal/src/app/engine/v2/features/contract-subscriptions/page.mdx
similarity index 98%
rename from apps/portal/src/app/engine/features/contract-subscriptions/page.mdx
rename to apps/portal/src/app/engine/v2/features/contract-subscriptions/page.mdx
index e27f74b89aa..f0eee2f533f 100644
--- a/apps/portal/src/app/engine/features/contract-subscriptions/page.mdx
+++ b/apps/portal/src/app/engine/v2/features/contract-subscriptions/page.mdx
@@ -132,7 +132,7 @@ Engine will call your webhook URL with event logs and transaction details for yo
#### Verifying webhook signatures
-See [Webhooks](/engine/features/webhooks) for more information on managing webhooks and verifying webhook signatures.
+See [Webhooks](/engine/v2/features/webhooks) for more information on managing webhooks and verifying webhook signatures.
## FAQ
diff --git a/apps/portal/src/app/engine/features/contracts/page.mdx b/apps/portal/src/app/engine/v2/features/contracts/page.mdx
similarity index 100%
rename from apps/portal/src/app/engine/features/contracts/page.mdx
rename to apps/portal/src/app/engine/v2/features/contracts/page.mdx
diff --git a/apps/portal/src/app/engine/features/custom-chains/page.mdx b/apps/portal/src/app/engine/v2/features/custom-chains/page.mdx
similarity index 100%
rename from apps/portal/src/app/engine/features/custom-chains/page.mdx
rename to apps/portal/src/app/engine/v2/features/custom-chains/page.mdx
diff --git a/apps/portal/src/app/engine/features/gasless-transactions/page.mdx b/apps/portal/src/app/engine/v2/features/gasless-transactions/page.mdx
similarity index 91%
rename from apps/portal/src/app/engine/features/gasless-transactions/page.mdx
rename to apps/portal/src/app/engine/v2/features/gasless-transactions/page.mdx
index 1d0688d6e7a..8dd16e3f5cf 100644
--- a/apps/portal/src/app/engine/features/gasless-transactions/page.mdx
+++ b/apps/portal/src/app/engine/v2/features/gasless-transactions/page.mdx
@@ -33,10 +33,10 @@ Examples:
If your contract supports meta-transactions, use Engine as a relayer to send meta-transactions that are signed by your users' wallets.
-[Learn more about relayers in Engine.](/engine/features/relayers)
+[Learn more about relayers in Engine.](/engine/v2/features/relayers)
### Send transactions with smart accounts
If your users have smart accounts, use Engine backend wallets to transact on behalf of smart accounts.
-[Learn more about smart accounts in Engine.](/engine/features/smart-wallets)
+[Learn more about smart accounts in Engine.](/engine/v2/features/smart-wallets)
diff --git a/apps/portal/src/app/engine/features/keypair-authentication/page.mdx b/apps/portal/src/app/engine/v2/features/keypair-authentication/page.mdx
similarity index 95%
rename from apps/portal/src/app/engine/features/keypair-authentication/page.mdx
rename to apps/portal/src/app/engine/v2/features/keypair-authentication/page.mdx
index 06a502ce4d2..02f860b2cc6 100644
--- a/apps/portal/src/app/engine/features/keypair-authentication/page.mdx
+++ b/apps/portal/src/app/engine/v2/features/keypair-authentication/page.mdx
@@ -19,7 +19,7 @@ Keypair authentication is an advanced feature and must be explicitly enabled.
[Contact us](https://thirdweb.com/contact-us) to enable this on your managed Engine instance.
**Don't need short-lived access tokens?**
-Utilize [Access Tokens](/engine/features/access-tokens) which are valid until deleted.
+Utilize [Access Tokens](/engine/v2/features/access-tokens) which are valid until deleted.
@@ -162,4 +162,4 @@ The following algorithms can be used.
Refer to the OpenSSL documentation on generating keypairs for different algorithms.
-Remember to change `algorithm` in the `jsonwebtoken.sign()` call on [Step 3. Sign a JWT with your private key](/engine/features/keypair-auth#3-sign-a-jwt-with-your-private-key).
+Remember to change `algorithm` in the `jsonwebtoken.sign()` call on [Step 3. Sign a JWT with your private key](/engine/v2/features/keypair-auth#3-sign-a-jwt-with-your-private-key).
diff --git a/apps/portal/src/app/engine/features/preventing-duplicate-transactions/page.mdx b/apps/portal/src/app/engine/v2/features/preventing-duplicate-transactions/page.mdx
similarity index 100%
rename from apps/portal/src/app/engine/features/preventing-duplicate-transactions/page.mdx
rename to apps/portal/src/app/engine/v2/features/preventing-duplicate-transactions/page.mdx
diff --git a/apps/portal/src/app/engine/features/relayers/page.mdx b/apps/portal/src/app/engine/v2/features/relayers/page.mdx
similarity index 98%
rename from apps/portal/src/app/engine/features/relayers/page.mdx
rename to apps/portal/src/app/engine/v2/features/relayers/page.mdx
index 67493ea50de..9c9eedfe07e 100644
--- a/apps/portal/src/app/engine/features/relayers/page.mdx
+++ b/apps/portal/src/app/engine/v2/features/relayers/page.mdx
@@ -20,7 +20,7 @@ Enable users to claim, transfer, list, or burn NFTs with no gas. [Learn more abo
## Requirements
-- Your Engine instance has a [backend wallet](/engine/features/backend-wallets) with funds.
+- Your Engine instance has a [backend wallet](/engine/v2/features/backend-wallets) with funds.
- The target contract must support one of:
- [EIP-2771 meta transactions](https://eips.ethereum.org/EIPS/eip-2771) \*
- [EIP-2612 permit approval](https://eips.ethereum.org/EIPS/eip-2612)
diff --git a/apps/portal/src/app/engine/features/security/page.mdx b/apps/portal/src/app/engine/v2/features/security/page.mdx
similarity index 100%
rename from apps/portal/src/app/engine/features/security/page.mdx
rename to apps/portal/src/app/engine/v2/features/security/page.mdx
diff --git a/apps/portal/src/app/engine/features/cancelling-transactions/page.mdx b/apps/portal/src/app/engine/v2/features/transactions/page.mdx
similarity index 51%
rename from apps/portal/src/app/engine/features/cancelling-transactions/page.mdx
rename to apps/portal/src/app/engine/v2/features/transactions/page.mdx
index 3db25d370ea..f7b098b01a4 100644
--- a/apps/portal/src/app/engine/features/cancelling-transactions/page.mdx
+++ b/apps/portal/src/app/engine/v2/features/transactions/page.mdx
@@ -1,12 +1,38 @@
-import cancelTxImage from "../../assets/cancel-transaction-button.png";
+
import { createMetadata, DocImage } from "@doc";
+import lifecycleImage from "../../assets/tx-lifecycle.webp";
+import cancelTxImage from "../../assets/cancel-transaction-button.png";
-export const metadata = createMetadata({
- title: "Cancelling Transactions | thirdweb Engine",
- description: "Cancel transactions in Engine to remove it from the queue.",
-});
+# Engine Transactions
+
+Blockchain **read** calls (e.g. get token balance) are synchronous and will return the value read.
+
+Blockchain **write** calls (e.g. transfer tokens) are asynchronous:
+
+- Your app backend sends a write transaction to Engine.
+- Engine enqueues the job and returns a reference to the job: `queueId`.
+ - If `queueId` is returned, this transaction will be attempted.
+ - If `queueId` is not returned, this transaction failed to be added to the queue and will not be attempted.
+- Engine will attempt to submit the transaction from your specified backend wallet.
+ - If there is an error (failed simulation, out of gas), the transaction is set to `errored` and will not be re-attempted.
+- Engine polls to check if the transaction is mined. If it is, the transaction is set to `mined`.
+- If the transaction is not mined after some duration, Engine re-submits the transaction with aggressive gas settings. This transaction is sent with the same nonce and will be mined at most once.
+
+
+
+## Learn what each transaction status means
+
+- **Queued**: The transaction was received by Engine and waiting in the transaction queue.
+- **Sent**: The transaction was successfully sent to RPC.
+- **Mined**: The transaction was successfully mined onchain.
+- **Cancelled**: The transaction was cancelled by the user.
+- **Errored**: The transaction failed to be sent to RPC or to the chain's nodes. This can happen for many reasons (malformed transaction, failed simulation, too low gas).
-# Cancelling Transactions
+## Cancelling Transactions
Engine submits transactions to the blockchain within 5-10 seconds of receiving a request. During gas or traffic spikes, transactions may take longer to be mined.
@@ -52,4 +78,4 @@ Select the **Cancel** icon next to a queued transaction in the Tranasctions tabl
## Cancel all queued transactions
-Coming soon.
+Coming soon.
\ No newline at end of file
diff --git a/apps/portal/src/app/engine/features/webhooks/page.mdx b/apps/portal/src/app/engine/v2/features/webhooks/page.mdx
similarity index 100%
rename from apps/portal/src/app/engine/features/webhooks/page.mdx
rename to apps/portal/src/app/engine/v2/features/webhooks/page.mdx
diff --git a/apps/portal/src/app/engine/get-started/page.mdx b/apps/portal/src/app/engine/v2/get-started/page.mdx
similarity index 95%
rename from apps/portal/src/app/engine/get-started/page.mdx
rename to apps/portal/src/app/engine/v2/get-started/page.mdx
index 6c68ca5937d..27d3f5c6315 100644
--- a/apps/portal/src/app/engine/get-started/page.mdx
+++ b/apps/portal/src/app/engine/v2/get-started/page.mdx
@@ -89,7 +89,7 @@ Engine endpoints require authentication.
- Create **access tokens** for your backends to call the Engine API. _These are secrets that should be stored securely._
- Revoke permissions at any time.
-Learn more about [admins](/engine/features/admins) and [access tokens](/engine/features/access-tokens).
+Learn more about [admins](/engine/v2/features/admins) and [access tokens](/engine/v2/features/access-tokens).
## Create backend wallets
@@ -99,7 +99,7 @@ Learn more about [admins](/engine/features/admins) and [access tokens](/engine/f
- Create or import a backend wallet.
- Specify the backend wallet to use when calling the Engine API.
-[Learn more about backend wallets.](/engine/features/backend-wallets)
+[Learn more about backend wallets.](/engine/v2/features/backend-wallets)
## Interact with the blockchain
@@ -107,7 +107,7 @@ Here are a few example API calls.
-Tip: Use the [TypeScript SDK](/engine/references/typescript) for type-safety.
+Tip: Use the [TypeScript SDK](/engine/v2/references/typescript) for type-safety.
@@ -225,4 +225,4 @@ Get notified when a transaction is mined, in addition to other wallet and transa
- Navigate to the **Webhooks** tab on the Engine dashboard.
- Create a new webhook URL.
-[Learn more about webhooks.](/engine/features/webhooks)
+[Learn more about webhooks.](/engine/v2/features/webhooks)
\ No newline at end of file
diff --git a/apps/portal/src/app/engine/guides/airdrop-nfts/page.mdx b/apps/portal/src/app/engine/v2/guides/airdrop-nfts/page.mdx
similarity index 97%
rename from apps/portal/src/app/engine/guides/airdrop-nfts/page.mdx
rename to apps/portal/src/app/engine/v2/guides/airdrop-nfts/page.mdx
index 341ccf08778..cdc41cf7d14 100644
--- a/apps/portal/src/app/engine/guides/airdrop-nfts/page.mdx
+++ b/apps/portal/src/app/engine/v2/guides/airdrop-nfts/page.mdx
@@ -25,7 +25,7 @@ Engine makes it effortless for any developer to airdrop NFTs at scale. You spons
## Prerequisites
- An Engine instance
-- A [backend wallet](/engine/features/backend-wallets) with currency to pay for gas
+- A [backend wallet](/engine/v2/features/backend-wallets) with currency to pay for gas
- A deployed NFT contract that can be claimed by the backend wallet
- A client ID and secret key from your Team > Project > Settings page.
diff --git a/apps/portal/src/app/engine/guides/nft-checkout/page.mdx b/apps/portal/src/app/engine/v2/guides/nft-checkout/page.mdx
similarity index 97%
rename from apps/portal/src/app/engine/guides/nft-checkout/page.mdx
rename to apps/portal/src/app/engine/v2/guides/nft-checkout/page.mdx
index 06fcb157e2b..0cdf59fa79c 100644
--- a/apps/portal/src/app/engine/guides/nft-checkout/page.mdx
+++ b/apps/portal/src/app/engine/v2/guides/nft-checkout/page.mdx
@@ -26,8 +26,8 @@ The buyer receives the NFT without requiring wallet signatures or gas funds.
- A thirdweb client ID and secret key from your Team > Project > Settings page.
- An Engine instance
-- A [backend wallet](/engine/features/backend-wallets) with currency to pay for gas
-- An [access token](/engine/features/authentication) for your Engine instance
+- A [backend wallet](/engine/v2/features/backend-wallets) with currency to pay for gas
+- An [access token](/engine/v2/features/authentication) for your Engine instance
- A deployed NFT contract that can be claimed by the backend wallet
- A [Stripe account](https://dashboard.stripe.com/register) on test mode (no real payments will be made)
diff --git a/apps/portal/src/app/engine/v2/layout.tsx b/apps/portal/src/app/engine/v2/layout.tsx
new file mode 100644
index 00000000000..356fd8693e1
--- /dev/null
+++ b/apps/portal/src/app/engine/v2/layout.tsx
@@ -0,0 +1,27 @@
+import { DocLayout } from "@/components/Layouts/DocLayout";
+import { createMetadata } from "@doc";
+import { EngineVersionSelector } from "../../../components/others/EngineVersionSelector";
+import { sidebar } from "./sidebar";
+
+export default async function Layout(props: { children: React.ReactNode }) {
+ return (
+
+
Engine
+
+
+ }
+ >
+ {props.children}
+
+ );
+}
+
+export const metadata = createMetadata({
+ title: "Engine",
+ description:
+ "Engine is a backend HTTP server that calls smart contracts using your managed backend wallets.",
+});
diff --git a/apps/portal/src/app/engine/v2/page.mdx b/apps/portal/src/app/engine/v2/page.mdx
new file mode 100644
index 00000000000..6e797a02fd2
--- /dev/null
+++ b/apps/portal/src/app/engine/v2/page.mdx
@@ -0,0 +1,97 @@
+import OverviewImage from "./assets/engine-overview.png";
+import { DocImage, FeatureCard, OpenSourceCard, Callout } from "@doc";
+import { createMetadata } from "@/components/Document";
+import { ActivityIcon, CircleCheckIcon, RotateCcwIcon, BanIcon, FileIcon, MessageCircleIcon, WalletIcon, BlocksIcon, ArrowLeftRightIcon, SlidersHorizontalIcon } from "lucide-react";
+import SupportedChains from "../../_images/supported-chains.png";
+
+
+export const metadata = createMetadata({
+ title: "thirdweb Engine",
+ description: "An open-source, backend server that reads, writes, and deploys contracts at production scale.",
+});
+
+# Engine
+
+Engine provides a way to read and write to the blockchain at scale through simple API endpoints.
+
+
+
+
+ Engine Cloud is currently in beta as we are adding more features, endpoints, and improving performance. Engine Standard and Premium have been
+ rebranded to Engine Dedicated V2 with Engine Dedicated V3 coming soon.
+
+ Get started with Engine Cloud for free by creating a project on your thirdweb dashboard.
+
+
+## Features
+
+
+
+## Engine Cloud vs. Dedicated
+
+| Feature | Cloud ☁️ | Dedicated (V3), Coming Soon |
+|--------------------|-------------------------------------------|------------------------------------------|
+| Wallets | Server Wallets | Server Wallets, AWS, GCP, Circle |
+| Database Backups | ❌ | 30 Day Backups |
+| Infrastructure | Shared | Isolated |
+| Rate Limits | [Limited by RPC Plan](https://thirdweb.com/pricing) | Unlimited |
+| Pricing | [See pricing page](https://thirdweb.com/pricing) | [See pricing page](https://thirdweb.com/pricing) |
+
+
+## Supported Chains
+
+Engine is supported on every EVM compatible chain and private subnets. To view the full list, visit [thirdweb chainlist](https://thirdweb.com/chainlist?service=engine).
+
+
+
+
diff --git a/apps/portal/src/app/engine/v2/production-checklist/page.mdx b/apps/portal/src/app/engine/v2/production-checklist/page.mdx
new file mode 100644
index 00000000000..e702762ca08
--- /dev/null
+++ b/apps/portal/src/app/engine/v2/production-checklist/page.mdx
@@ -0,0 +1,21 @@
+# Production Checklist
+
+Before deploying Engine to production, ensure you have completed the following steps.
+
+- [ ] Ensure access tokens are not accessible from your frontend. The Engine API is intended to be called from your backend only.
+
+ **Exception: Relayer endpoints do not require access tokens.**
+
+- [ ] Securely store access tokens, vault admin keys, and your project's secret key. You may use a tool such as AWS Secrets Manager, Google Secrets Manager, and others.
+- [ ] Use labels to keep track of your wallets, admins, and access tokens.
+- [ ] Use access token with expirations to grant time-bound access.
+
+After deploying Engine to production, ensure you check regularly to keep your setup secure.
+- [ ] Regularly review the admins list to remove inactive and former team members.
+- [ ] Rotate credentials such as access tokens, admin keys, and your project's secret key if they have been compromised.
+- [ ] Ensure your server wallets have sufficient funds. Use [wallet webhooks](/engine/v2/features/webhooks) to alert when your gas balance is low.
+
+## Recommended Actions
+
+- Use a wallet backed by AWS KMS or Google KMS. Wallet access is always recoverable and your wallet's private keys are never exposed.
+- If using a local wallet: **back up the private key**. Engine cannot recover private keys if the encrypted stored data is lost or corrupted.
\ No newline at end of file
diff --git a/apps/portal/src/app/engine/references/typescript/page.mdx b/apps/portal/src/app/engine/v2/references/typescript/page.mdx
similarity index 100%
rename from apps/portal/src/app/engine/references/typescript/page.mdx
rename to apps/portal/src/app/engine/v2/references/typescript/page.mdx
diff --git a/apps/portal/src/app/engine/security/page.mdx b/apps/portal/src/app/engine/v2/security/page.mdx
similarity index 100%
rename from apps/portal/src/app/engine/security/page.mdx
rename to apps/portal/src/app/engine/v2/security/page.mdx
diff --git a/apps/portal/src/app/engine/self-host/page.mdx b/apps/portal/src/app/engine/v2/self-host/page.mdx
similarity index 91%
rename from apps/portal/src/app/engine/self-host/page.mdx
rename to apps/portal/src/app/engine/v2/self-host/page.mdx
index e38bdd92887..9832f546c06 100644
--- a/apps/portal/src/app/engine/self-host/page.mdx
+++ b/apps/portal/src/app/engine/v2/self-host/page.mdx
@@ -1,19 +1,15 @@
import { Callout } from "@doc";
+export const metadata = {
+ title: "Self-Host Engine",
+ description: "Learn how to self-host thirdweb Engine on your own infrastructure for free.",
+};
+
# Self-Host Instructions
-Self-host Engine on your own infrastructure for free and manage your self-hosted Engine from the [thirdweb
+Learn how to self-host Engine on your own infrastructure for free and manage your self-hosted Engine from the [thirdweb
dashboard](https://thirdweb.com/team/~/~/engine).
-
-
-[Get Engine hosted by thirdweb.](https://thirdweb.com/team/~/~/engine/create)
-
-
-
### Requirements
- [Docker](https://docs.docker.com/get-docker/)
@@ -63,7 +59,7 @@ docker run \
| `ENABLE_HTTPS` | Self-sign a certificate to serve API requests on HTTPS. Set to `true` if running Engine locally only. (Default: `false`) |
| `LOG_LEVEL` | Determines the logging severity level. Adjust for finer control over logged information. (Default: `debug`) |
| `PRUNE_TRANSACTIONS` | When `false`, Engine prevents the pruning/deletion of processed transaction data. (Default: `true`) |
-| `ENABLE_KEYPAIR_AUTH` | Enables [Keypair Authentication](/engine/features/keypair-authentication). |
+| `ENABLE_KEYPAIR_AUTH` | Enables [Keypair Authentication](/engine/v2/features/keypair-authentication). |
| `TRUST_PROXY` | When `true`, trust the `X-Forwarded-For` header to allow Engine to use the correct client IP address for the IP allowlist. |
* Required
@@ -92,7 +88,7 @@ To manage your Engine instance from the dashboard:
### Running Engine in production
-See the [Production Checklist](/engine/production-checklist#cloud-hosting) for best practices using Engine in a production environment.
+See the [Production Checklist](/engine/v2/production-checklist#cloud-hosting) for best practices using Engine in a production environment.
- Pin Engine Docker to a version to control when changes are introduced.
- `latest` may include major version changes which can introduce breaking changes.
@@ -117,7 +113,7 @@ Here are common troubleshooting tips:
- Ensure the Postgres DB connection URL and credentials are correct.
- Ensure the database name exists on the Postgres DB.
-See [Production Checklist](/engine/production-checklist#cloud-hosting) for best practices using Engine in a production environment.
+See [Production Checklist](/engine/v2/production-checklist#cloud-hosting) for best practices using Engine in a production environment.
#### Self-hosting recommendations
@@ -170,4 +166,4 @@ POSTGRES_CONNECTION_URL=postgres://postgres:postgres@localhost:5432/postgres?con
#### What is `x-forwarded-for` and how does it affect Engine?
-If you have engine running on a server behind a reverse proxy, you can set the `TRUST_PROXY` environment variable to `true` to trust the `X-Forwarded-For` header. Reverse proxies like Nginx or Apache will add this header to the request with the original client IP address, and setting this variable will allow Engine to use the correct IP address for the IP Allowlist. For more details on IP Allowlisting, refer to the [Security Features](/engine/features/security) page.
+If you have engine running on a server behind a reverse proxy, you can set the `TRUST_PROXY` environment variable to `true` to trust the `X-Forwarded-For` header. Reverse proxies like Nginx or Apache will add this header to the request with the original client IP address, and setting this variable will allow Engine to use the correct IP address for the IP Allowlist. For more details on IP Allowlisting, refer to the [Security Features](/engine/v2/features/security) page.
diff --git a/apps/portal/src/app/engine/sidebar.tsx b/apps/portal/src/app/engine/v2/sidebar.tsx
similarity index 62%
rename from apps/portal/src/app/engine/sidebar.tsx
rename to apps/portal/src/app/engine/v2/sidebar.tsx
index 74b8b337bb7..5742bf96b62 100644
--- a/apps/portal/src/app/engine/sidebar.tsx
+++ b/apps/portal/src/app/engine/v2/sidebar.tsx
@@ -1,40 +1,47 @@
import type { SideBar } from "@/components/Layouts/DocLayout";
+import {
+ BookMarkedIcon,
+ BracesIcon,
+ CloudIcon,
+ CodeIcon,
+ ExternalLinkIcon,
+ KeyIcon,
+ ListCheckIcon,
+ MessageCircleQuestionIcon,
+ RocketIcon,
+ ServerIcon,
+ ShieldQuestionIcon,
+ WalletIcon,
+ WrenchIcon,
+} from "lucide-react";
-const engineSlug = "/engine";
+const engineSlug = "/engine/v2";
export const sidebar: SideBar = {
name: "Engine",
links: [
{
name: "Overview",
- href: "/engine",
+ href: engineSlug,
+ icon: ,
},
{
name: "Playground",
href: "https://playground.thirdweb.com/engine/airdrop",
+ icon: ,
},
{
name: "Get Started",
href: `${engineSlug}/get-started`,
+ icon: ,
},
{
- name: "Production Checklist",
- href: `${engineSlug}/production-checklist`,
- },
- {
- name: "Self-Host",
- href: `${engineSlug}/self-host`,
- },
- {
- name: "Features",
+ name: "Key Concepts",
+ icon: ,
links: [
{
- name: "Backend Wallets",
- href: `${engineSlug}/features/backend-wallets`,
- },
- {
- name: "Wallet Credentials",
- href: `${engineSlug}/features/wallet-credentials`,
+ name: "Transactions",
+ href: `${engineSlug}/features/transactions`,
},
{
name: "Contracts",
@@ -52,10 +59,6 @@ export const sidebar: SideBar = {
name: "Webhooks",
href: `${engineSlug}/features/webhooks`,
},
- {
- name: "Cancelling Transactions",
- href: `${engineSlug}/features/cancelling-transactions`,
- },
{
name: "Preventing Duplicate Transactions",
href: `${engineSlug}/features/preventing-duplicate-transactions`,
@@ -91,7 +94,35 @@ export const sidebar: SideBar = {
],
},
{
- name: "Guides",
+ name: "Configure Wallets",
+ href: `${engineSlug}/configure-wallets`,
+ icon: ,
+ links: [
+ {
+ name: "Smart Server Wallet",
+ href: `${engineSlug}/configure-wallets/server-wallet`,
+ },
+ {
+ name: "AWS KMS",
+ href: `${engineSlug}/configure-wallets/aws-kms`,
+ },
+ {
+ name: "Google Cloud KMS",
+ href: `${engineSlug}/configure-wallets/gcp-kms`,
+ },
+ {
+ name: "Circle Wallet",
+ href: `${engineSlug}/configure-wallets/circle-wallet`,
+ },
+ {
+ name: "Wallet Credentials",
+ href: `${engineSlug}/configure-wallets/wallet-credentials`,
+ },
+ ],
+ },
+ {
+ name: "Tutorials",
+ icon: ,
links: [
{ name: "Airdrop NFTs", href: `${engineSlug}/guides/airdrop-nfts` },
{ name: "NFT Checkout", href: `${engineSlug}/guides/nft-checkout` },
@@ -100,22 +131,37 @@ export const sidebar: SideBar = {
{
name: "API Reference",
href: "https://thirdweb-engine.apidocumentation.com/",
+ icon: ,
},
{
name: "Typescript SDK",
href: `${engineSlug}/references/typescript`,
+ icon: ,
+ },
+ {
+ name: "Prod Checklist",
+ href: `${engineSlug}/production-checklist`,
+ icon: ,
+ },
+ {
+ name: "Self-Host",
+ href: `${engineSlug}/self-host`,
+ icon: ,
},
{
name: "Security",
href: `${engineSlug}/security`,
+ icon: ,
},
{
- name: "FAQ",
- href: `${engineSlug}/faq`,
+ name: "Troubleshoot",
+ href: `${engineSlug}/troubleshooting`,
+ icon: ,
},
{
- name: "Troubleshooting",
- href: `${engineSlug}/troubleshooting`,
+ name: "FAQ",
+ href: `${engineSlug}/faq`,
+ icon: ,
},
],
};
diff --git a/apps/portal/src/app/engine/troubleshooting/page.mdx b/apps/portal/src/app/engine/v2/troubleshooting/page.mdx
similarity index 95%
rename from apps/portal/src/app/engine/troubleshooting/page.mdx
rename to apps/portal/src/app/engine/v2/troubleshooting/page.mdx
index f06e5e6de7a..2a6d8d91aed 100644
--- a/apps/portal/src/app/engine/troubleshooting/page.mdx
+++ b/apps/portal/src/app/engine/v2/troubleshooting/page.mdx
@@ -44,7 +44,7 @@ Another common reason is the transaction ran out of gas. You can verify this by
If the transaction failed due to onchain logic, try to simulate the transaction (see above) to identify the reason.
-If the gas limit was reached, you may try [manually overriding the gas settings](https://portal.thirdweb.com/engine/features/contracts#override-gas-settings). Engine automatically estimates the gas limit through simulation, and it is not recommended to override the gas limit unless the estimation is incorrect.
+If the gas limit was reached, you may try [manually overriding the gas settings](https://portal.thirdweb.com/engine/v2/features/contracts#override-gas-settings). Engine automatically estimates the gas limit through simulation, and it is not recommended to override the gas limit unless the estimation is incorrect.
### Received "replacement transaction underpriced" error
diff --git a/apps/portal/src/app/engine/v3/configure-wallets/smart-server-wallet/page.mdx b/apps/portal/src/app/engine/v3/configure-wallets/smart-server-wallet/page.mdx
new file mode 100644
index 00000000000..54b041efea8
--- /dev/null
+++ b/apps/portal/src/app/engine/v3/configure-wallets/smart-server-wallet/page.mdx
@@ -0,0 +1,8 @@
+import { Details } from "@doc";
+
+# Server Wallets
+
+Smart server wallets are the recommended way to perform blockchain operations with Engine.
+
+You can create smart server wallets by navigating to Engine > Server Wallets in your project dashboard.
+
diff --git a/apps/portal/src/app/engine/v3/faq/page.mdx b/apps/portal/src/app/engine/v3/faq/page.mdx
new file mode 100644
index 00000000000..6fbd5b9e4b5
--- /dev/null
+++ b/apps/portal/src/app/engine/v3/faq/page.mdx
@@ -0,0 +1,5 @@
+import { Callout, Details } from "@doc";
+
+# Engine FAQs
+
+More information coming soon.
\ No newline at end of file
diff --git a/apps/portal/src/app/engine/v3/get-started/page.mdx b/apps/portal/src/app/engine/v3/get-started/page.mdx
new file mode 100644
index 00000000000..9200e2b9f7a
--- /dev/null
+++ b/apps/portal/src/app/engine/v3/get-started/page.mdx
@@ -0,0 +1,258 @@
+import { Callout, Step, Steps, Tabs, TabsContent, TabsTrigger, TabsList } from "@doc";
+
+# Get started
+
+Learn how to get started with thirdweb Engine. This guide will walk you through the steps to start building with thirdweb Engine by creating a Vault, server wallets, and integrating into your application.
+
+## Prerequisites
+
+- Create a thirdweb project. If you don't have a project yet, [learn how to create a project](/account/api-keys/create).
+
+## Engine Setup
+
+
+
+ In your project dashboard, navigate to **Engine** to get started.
+
+
+
+ Create a vault to manage your Engine's server wallets. After setup, you can manage your Vault to create additional access tokens or rotate admin keys.
+
+
+ Vault is thirdweb's key management service designed to store smart server wallets non-custodially. Learn more about [Vault].
+
+
+
+
+ Create a server wallet to perform blockchain actions with Engine.
+
+
+ Server wallets are smart wallets Engine uses to perform blockchain actions. [Learn more about server wallets](/engine/v2/configure-wallets/server-wallets).
+
+
+
+
+ To verify your server wallet setup and see how transactions work, you can send a test transaction in the next step. This sends a no-op transaction—a transaction with zero value—to your own wallet.
+
+ You can send additional test transactions or proceed with the full setup whenever you're ready.
+
+
+
+ Integrate Engine into your application using the thirdweb SDK or Engine API. [View full API reference.](https://client.scalar.com/workspace/default/request/yq_Wx56PL4Ur6jOZsAOpA)
+
+
+
+ Curl
+ JavaScript
+ Python
+ Go
+ C#
+
+
+
+ ```bash
+ curl -X POST "https://engine-cloud-dev-l8wt.chainsaw-dev.zeet.app/v1/write/contract" \
+ -H "Content-Type: application/json" \
+ -H "x-secret-key: " \
+ -H "x-vault-access-token: " \
+ -d '{
+ "executionOptions": {
+ "from": "",
+ "chainId": "84532"
+ },
+ "params": [
+ {
+ "contractAddress": "0x...",
+ "method": "function mintTo(address to, uint256 amount)",
+ "params": ["0x...", "100"]
+ }
+ ]
+ }'
+ ```
+
+
+
+
+ ```typescript
+ const response = await fetch(
+ "https://engine-cloud-dev-l8wt.chainsaw-dev.zeet.app/v1/write/contract",
+ {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ "x-secret-key": "",
+ "x-vault-access-token": "",
+ },
+ body: JSON.stringify({
+ executionOptions: {
+ from: "",
+ chainId: "84532",
+ },
+ params: [
+ {
+ contractAddress: "0x...",
+ method: "function mintTo(address to, uint256 amount)",
+ params: ["0x...", "100"],
+ },
+ ],
+ }),
+ }
+ );
+ ```
+
+
+
+ ```python
+ import requests
+ import json
+
+ url = "https://engine-cloud-dev-l8wt.chainsaw-dev.zeet.app/v1/write/contract"
+ headers = {
+ "Content-Type": "application/json",
+ "x-secret-key": "",
+ "x-vault-access-token": ""
+ }
+ payload = {
+ "executionOptions": {
+ "from": "",
+ "chainId": "84532"
+ },
+ "params": [
+ {
+ "contractAddress": "0x...",
+ "method": "function mintTo(address to, uint256 amount)",
+ "params": ["0x...", "100"]
+ }
+ ]
+ }
+
+ response = requests.post(url, headers=headers, json=payload)
+ result = response.json()
+ ```
+
+
+
+ ```go
+ package main
+
+ import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ )
+
+ func main() {
+ url := "https://engine-cloud-dev-l8wt.chainsaw-dev.zeet.app/v1/write/contract"
+
+ // Create the request payload
+ type Param struct {
+ ContractAddress string `json:"contractAddress"`
+ Method string `json:"method"`
+ Params []string `json:"params"`
+ }
+
+ type RequestBody struct {
+ ExecutionOptions struct {
+ From string `json:"from"`
+ ChainId string `json:"chainId"`
+ } `json:"executionOptions"`
+ Params []Param `json:"params"`
+ }
+
+ requestBody := RequestBody{
+ Params: []Param{
+ {
+ ContractAddress: "0x...",
+ Method: "function mintTo(address to, uint256 amount)",
+ Params: []string{"0x...", "100"},
+ },
+ },
+ }
+ requestBody.ExecutionOptions.From = ""
+ requestBody.ExecutionOptions.ChainId = "84532"
+
+ jsonData, _ := json.Marshal(requestBody)
+
+ // Create the HTTP request
+ req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("x-secret-key", "")
+ req.Header.Set("x-vault-access-token", "")
+
+ // Send the request
+ client := &http.Client{}
+ resp, err := client.Do(req)
+ if err != nil {
+ fmt.Println("Error:", err)
+ return
+ }
+ defer resp.Body.Close()
+
+ // Process the response
+ var result map[string]interface{}
+ json.NewDecoder(resp.Body).Decode(&result)
+ fmt.Println("Response:", result)
+ }
+ ```
+
+
+
+ ```
+ using System;
+ using System.Net.Http;
+ using System.Text;
+ using System.Text.Json;
+ using System.Threading.Tasks;
+
+ class Program
+ {
+ static async Task Main()
+ {
+ var url = "https://engine-cloud-dev-l8wt.chainsaw-dev.zeet.app/v1/write/contract";
+
+ var requestData = new
+ {
+ executionOptions = new
+ {
+ from = "",
+ chainId = "84532"
+ },
+ @params = new[]
+ {
+ new
+ {
+ contractAddress = "0x...",
+ method = "function mintTo(address to, uint256 amount)",
+ @params = new[] { "0x...", "100" }
+ }
+ }
+ };
+
+ var json = JsonSerializer.Serialize(requestData);
+ var content = new StringContent(json, Encoding.UTF8, "application/json");
+
+ using var httpClient = new HttpClient();
+ httpClient.DefaultRequestHeaders.Add("x-secret-key", "");
+ httpClient.DefaultRequestHeaders.Add("x-vault-access-token", "");
+
+ var response = await httpClient.PostAsync(url, content);
+ var responseContent = await response.Content.ReadAsStringAsync();
+
+ Console.WriteLine(responseContent);
+ }
+}
+ ```
+
+
+
+
+ You can use the full [TypeScript SDK](/references/typescript/v5/serverWallet) in your backend, allowing you to use:
+ - The full catalog of extension functions
+ - The prepareContractCall function to encode your transactions
+ - The full account interface, predefined chains, and more
+ The SDK handles encoding your transactions, signing them to Engine and polling for status.
+
+
+
+
diff --git a/apps/portal/src/app/engine/v3/layout.tsx b/apps/portal/src/app/engine/v3/layout.tsx
new file mode 100644
index 00000000000..183b051c7a1
--- /dev/null
+++ b/apps/portal/src/app/engine/v3/layout.tsx
@@ -0,0 +1,27 @@
+import { DocLayout } from "@/components/Layouts/DocLayout";
+import { createMetadata } from "@doc";
+import { EngineVersionSelector } from "../../../components/others/EngineVersionSelector";
+import { sidebar } from "./sidebar";
+
+export default async function Layout(props: { children: React.ReactNode }) {
+ return (
+
+
Engine
+
+
+ }
+ >
+ {props.children}
+
+ );
+}
+
+export const metadata = createMetadata({
+ title: "Engine V3",
+ description:
+ "Engine is a backend HTTP server that calls smart contracts using your managed backend wallets.",
+});
diff --git a/apps/portal/src/app/engine/v3/page.mdx b/apps/portal/src/app/engine/v3/page.mdx
new file mode 100644
index 00000000000..78293334759
--- /dev/null
+++ b/apps/portal/src/app/engine/v3/page.mdx
@@ -0,0 +1,97 @@
+import { DocImage, FeatureCard, OpenSourceCard, Callout } from "@doc";
+import { createMetadata } from "@/components/Document";
+import { ActivityIcon, CircleCheckIcon, RotateCcwIcon, BanIcon, FileIcon, MessageCircleIcon, WalletIcon, BlocksIcon, ArrowLeftRightIcon, SlidersHorizontalIcon } from "lucide-react";
+import SupportedChains from "../../_images/supported-chains.png";
+
+
+export const metadata = createMetadata({
+ title: "thirdweb Engine",
+ description: "An open-source, backend server that reads, writes, and deploys contracts at production scale.",
+});
+
+# Engine
+
+Engine provides a way to read and write to the blockchain at scale through simple API endpoints.
+
+
+
+
+We just launched Engine Cloud in beta — we're actively adding new features, endpoints, and performance improvements.
+Engine Standard and Premium have now been rebranded as Engine Dedicated V2, with Engine Dedicated V3 on the way.
+
+Looking for the previous version? [Head back to the Engine V2 documentation.](/engine/v2)
+
+
+## Features
+
+
+
+## Engine Cloud vs. Dedicated
+
+| Feature | Cloud ☁️ | Dedicated (Coming Soon) |
+|--------------------|-------------------------------------------|------------------------------------------|
+| Wallets | Server Wallets | Server Wallets, AWS, GCP, Circle |
+| Database Backups | ❌ | 30 Day Backups |
+| Infrastructure | Shared | Isolated |
+| Rate Limits | [Limited by RPC Plan](https://thirdweb.com/pricing) | Unlimited |
+| Pricing | [See pricing page](https://thirdweb.com/pricing) | [See pricing page](https://thirdweb.com/pricing) |
+
+
+## Supported Chains
+
+Engine is supported on every EVM compatible chain and private subnets. To view the full list, visit [thirdweb chainlist](https://thirdweb.com/chainlist?service=engine).
+
+
+
+
diff --git a/apps/portal/src/app/engine/v3/sidebar.tsx b/apps/portal/src/app/engine/v3/sidebar.tsx
new file mode 100644
index 00000000000..a7a269ed155
--- /dev/null
+++ b/apps/portal/src/app/engine/v3/sidebar.tsx
@@ -0,0 +1,81 @@
+import type { SideBar } from "@/components/Layouts/DocLayout";
+import {
+ BracesIcon,
+ CloudIcon,
+ CodeIcon,
+ ExternalLinkIcon,
+ KeyIcon,
+ MessageCircleQuestionIcon,
+ RocketIcon,
+ ShieldQuestionIcon,
+ WalletIcon,
+ WrenchIcon,
+} from "lucide-react";
+
+const engineV3Slug = "/engine/v3";
+
+export const sidebar: SideBar = {
+ name: "Engine",
+ links: [
+ {
+ name: "Overview",
+ href: engineV3Slug,
+ icon: ,
+ },
+ {
+ name: "Playground",
+ href: "https://playground.thirdweb.com/engine/airdrop",
+ icon: ,
+ },
+ {
+ name: "Get Started",
+ href: `${engineV3Slug}/get-started`,
+ icon: ,
+ },
+ {
+ name: "Key Concepts",
+ icon: ,
+ links: [
+ {
+ name: "Vault",
+ href: "/vault",
+ },
+ ],
+ },
+ {
+ name: "Configure Wallets",
+ icon: ,
+ links: [
+ {
+ name: "Smart Server Wallet",
+ href: `${engineV3Slug}/configure-wallets/smart-server-wallet`,
+ },
+ ],
+ },
+ {
+ name: "API Reference",
+ href: "https://engine.thirdweb.com/reference",
+ icon: ,
+ },
+ {
+ name: "TypeScript SDK",
+ href: "/references/typescript/v5/serverWallet",
+ icon: ,
+ },
+ {
+ name: "Security",
+ href: "/vault/security",
+ icon: ,
+ },
+ {
+ name: "Troubleshoot",
+ href: `${engineV3Slug}/troubleshoot`,
+ icon: ,
+ },
+ {
+ name: "FAQ",
+ href: `${engineV3Slug}/faq`,
+ icon: ,
+ },
+ ],
+};
diff --git a/apps/portal/src/app/engine/v3/troubleshoot/page.mdx b/apps/portal/src/app/engine/v3/troubleshoot/page.mdx
new file mode 100644
index 00000000000..3ffcea0b9b3
--- /dev/null
+++ b/apps/portal/src/app/engine/v3/troubleshoot/page.mdx
@@ -0,0 +1,3 @@
+# Engine Troubleshoot Guide
+
+More information coming soon.
\ No newline at end of file
diff --git a/apps/portal/src/app/engine/v3/typescript-sdk/page.mdx b/apps/portal/src/app/engine/v3/typescript-sdk/page.mdx
new file mode 100644
index 00000000000..9ccc021b193
--- /dev/null
+++ b/apps/portal/src/app/engine/v3/typescript-sdk/page.mdx
@@ -0,0 +1,58 @@
+# Engine TypeScript SDK
+
+You can use the full TypeScript thirdweb SDK in your backend, allowing you to use:
+- The full catalog of extension functions
+- The prepareContractCall function to encode your transactions
+- The full account interface, predefined chains, and more
+The SDK handles encoding your transactions, signing them to Engine and polling for status.
+
+## Example
+
+Install SDK
+
+```bash
+npm install thirdweb
+```
+
+
+```typescript
+import {
+ createThirdwebClient,
+ sendTransaction,
+ getContract,
+ Engine,
+} from "thirdweb";
+import { baseSepolia } from "thirdweb/chains";
+import { claimTo } from "thirdweb/extensions/1155";
+
+// Create a thirdweb client
+const client = createThirdwebClient({
+ secretKey: "",
+});
+
+// Create a server wallet
+const serverWallet = Engine.serverWallet({
+ client,
+ address: "",
+ vaultAccessToken: "",
+});
+
+// Prepare the transaction
+const transaction = claimTo({
+ contract: getContract({
+ client,
+ address: "0x...", // Address of the ERC1155 token contract
+ chain: baseSepolia, // Chain of the ERC1155 token contract
+ }),
+ to: "0x...", // The address of the user to mint to
+ tokenId: 0n, // The token ID of the NFT to mint
+ quantity: 1n, // The quantity of NFTs to mint
+});
+
+// Send the transaction via Engine
+const result = await sendTransaction({
+ account: serverWallet,
+ transaction,
+});
+console.log("Transaction hash:", result.transactionHash);
+```
\ No newline at end of file
diff --git a/apps/portal/src/app/infrastructure/page.mdx b/apps/portal/src/app/infrastructure/page.mdx
index 7361cc05de9..f632e6d15b9 100644
--- a/apps/portal/src/app/infrastructure/page.mdx
+++ b/apps/portal/src/app/infrastructure/page.mdx
@@ -26,13 +26,13 @@ All the infrastructure to scale and build production grade applications.
}
+ iconUrl={}
/>
- }
- />
+ }
+ />
}
- />
-
- }
- />
+ title="Custom Blueprints"
+ description="Transform and enrich data easily to suit your needs."
+ iconUrl={}
+ />
+
+ }
+ />
diff --git a/apps/portal/src/app/nebula/page.mdx b/apps/portal/src/app/nebula/page.mdx
index a549cec5604..490248446ca 100644
--- a/apps/portal/src/app/nebula/page.mdx
+++ b/apps/portal/src/app/nebula/page.mdx
@@ -1,4 +1,4 @@
-import { Wallet, File, MessageCircle, Braces, Bot, Blocks } from "lucide-react";
+import { WalletIcon, FileIcon, MessageCircleIcon, BracesIcon, BotIcon, BlocksIcon } from "lucide-react";
import { DocImage, createMetadata, FeatureCard, GithubTemplateCard, Stack, Grid, ArticleCard, ArticleIconCard } from "@doc";
import NebulaDiagram from "./assets/nebula-diagram.png";
import SupportedChains from "../_images/supported-chains.png";
@@ -40,26 +40,26 @@ Nebula is currently live in Beta.
}
+ iconUrl={}
/>
- }
- />
+ }
+ />
}
- />
+ title="Wallet Integration"
+ description="Connect with over 500+ EOAs, in-app wallets, and smart wallets with session keys"
+ iconUrl={}
+ />
}
- />
+ title="Framework Integration"
+ description="Integrate with popular AI orchestration frameworks"
+ iconUrl={}
+ />
## Video Tutorials
diff --git a/apps/portal/src/app/vault/faqs/page.mdx b/apps/portal/src/app/vault/faqs/page.mdx
new file mode 100644
index 00000000000..4ea10c52724
--- /dev/null
+++ b/apps/portal/src/app/vault/faqs/page.mdx
@@ -0,0 +1,25 @@
+import { Details } from "@doc";
+
+# Vault FAQs
+
+
+***thirdweb vault is entirely non-custodial.***
+
+This means that if you lose your keys and your recovery code, *you have no means of recovering any of your EOAs, any funds stored in them, or any smart accounts or other contracts your EOAs might own.*
+
+thirdweb *cannot* help you in such a scenario.
+
+While storing all keys with yourself is the most secure way to use thirdweb vault, the lack of recovery options might be inconvenient or scary. As a compromise, when used with Engine Cloud, thirdweb allows you to store a backup of your rotation code with us. This way if you ever lose your admin key, we can let you rotate it as long as you can access the project this vault was initialised for.
+
+***is this still non-custodial?***
+
+yes.
+
+thirdweb cannot access any of your wallets or created entities with your rotation code alone.
+
+a “rotation-code” only allows the “service account rotate” operation, which will invalidate your admin key and all existing access tokens.
+
+There is no way for thirdweb to “silently” access your vault without your knowledge with only the recovery code.
+
+Rotating your engine’s vault account through a thirdweb-stored rotation code requires a signature from your wallet. You will also be able to see rotation history, the thirdweb account which initiated this rotation, and their wallet signature.
+
\ No newline at end of file
diff --git a/apps/portal/src/app/vault/get-started/page.mdx b/apps/portal/src/app/vault/get-started/page.mdx
new file mode 100644
index 00000000000..0762bda870c
--- /dev/null
+++ b/apps/portal/src/app/vault/get-started/page.mdx
@@ -0,0 +1,15 @@
+import { Callout } from "@doc";
+import { createMetadata } from "@/components/Document";
+
+# Get Started with Vault
+
+
+Vault is currently in beta as a part of Engine Cloud and will expand into more products. [Learn how to setup and manage your Vault with thirdweb Engine.](/engine/v3/get-started)
+
+
+
+## Manage Vault
+
+To manage your Vault, navigate to **Engine > Vault** in your project dashboard.
+
+Here you can create and manage access tokens and rotate your admin key.
\ No newline at end of file
diff --git a/apps/portal/src/app/vault/key-concepts/access-control/page.mdx b/apps/portal/src/app/vault/key-concepts/access-control/page.mdx
new file mode 100644
index 00000000000..41d38a1eb3a
--- /dev/null
+++ b/apps/portal/src/app/vault/key-concepts/access-control/page.mdx
@@ -0,0 +1,111 @@
+
+
+# Metadata-Based Access Control
+
+thirdweb Vault uses metadata patterns to map organizational structures directly into access control policies, eliminating the need to duplicate organizational hierarchies within the key management system.
+
+## Entity Tagging
+
+Each EOA can be tagged with arbitrary metadata key-value pairs representing organizational attributes:
+
+```json
+{
+ "team": "trading",
+ "region": "apac",
+ "purpose": "treasury",
+ "riskLevel": "high"
+}
+```
+
+## Pattern Matching with Rules
+
+Access tokens can be scoped using metadata rules that define precise access patterns:
+
+```json
+{
+ "metadataPatterns": [
+ {
+ "key": "team",
+ "rule": {
+ "pattern": "^trading$"
+ }
+ },
+ {
+ "key": "riskLevel",
+ "rule": {
+ "op": "lessThan",
+ "value": 3
+ }
+ }
+ ]
+}
+```
+
+## Practical Implementation Examples
+
+### Departmental Segregation
+
+An organization can create EOAs tagged with departmental metadata and issue access tokens that respect organizational boundaries:
+
+```json
+// Policy component for trading department
+{
+ "type": "eoa:signTransaction",
+ "allowlist": [],
+ "metadataPatterns": [
+ {
+ "key": "department",
+ "rule": {
+ "pattern": "^trading$"
+ }
+ },
+ {
+ "key": "region",
+ "rule": {
+ "pattern": "apac"
+ }
+ }
+ ],
+ "payloadPatterns": {
+ "chainId": [
+ {
+ "pattern": "^(1|137)$"
+ }
+ ],
+ "value": [
+ {
+ "op": "lessThan",
+ "value": "1000000000000000000"
+ }
+ ]
+ }
+}
+```
+
+### Multi-Team Collaboration
+
+For entities requiring shared access across teams:
+
+```json
+// EOA metadata
+{
+ "teams": "finance,trading,compliance",
+ "purpose": "treasury"
+}
+
+// Policy for finance team access
+{
+ "type": "eoa:signMessage",
+ "allowlist": [],
+ "metadataPatterns": [
+ {
+ "key": "teams",
+ "rule": {
+ "pattern": "finance"
+ }
+ }
+ ],
+ "chainId": 1,
+ "messagePattern": "^Confirm treasury operation:"
+}
+```
\ No newline at end of file
diff --git a/apps/portal/src/app/vault/key-concepts/access-tokens/page.mdx b/apps/portal/src/app/vault/key-concepts/access-tokens/page.mdx
new file mode 100644
index 00000000000..14fdd8b85cd
--- /dev/null
+++ b/apps/portal/src/app/vault/key-concepts/access-tokens/page.mdx
@@ -0,0 +1,42 @@
+
+# Access Tokens
+Access tokens are a core security mechanism in thirdweb Vault that enable secure, controlled delegation of wallet operations. Created by either user accounts or service accounts, access tokens allow precise, policy-based access to account-owned entities like EOAs.
+
+### Purpose and Benefits
+
+Access tokens serve several critical functions:
+
+- **Delegation without sharing keys**: Grant specific capabilities to services, applications, or team members without exposing your admin key
+- **Fine-grained permission control**: Limit exactly what operations can be performed and under what conditions
+- **Instant revocation**: Immediately terminate access when needed
+- **Auditable access paths**: Track and monitor who has what level of access to your entities
+
+### Policy-Based Control
+
+Each access token is configured with a set of policies that define:
+
+1. **Which operations** can be performed (e.g., signing transactions, reading wallet information)
+2. **Which entities** can be accessed (using allowlists or metadata patterns)
+3. **What constraints** apply to each operation (e.g., transaction value limits, allowed chains)
+
+An access token can only perform operations explicitly permitted by its policy. For example, you might create an access token that can only:
+
+- Sign transactions on Ethereum mainnet
+- With a maximum value of 1 ETH
+- To a specific set of contract addresses
+- Using only wallets tagged with a particular purpose
+
+### Practical Applications
+
+Access tokens enable critical workflows for blockchain applications:
+
+- **Application integrations**: Let your application sign transactions without holding private keys
+- **Team collaboration**: Grant different team members appropriate access levels to shared wallets
+- **Automated processes**: Enable secure automated signing for scheduled operations
+- **Temporary access**: Create time-limited tokens for specific projects or partnerships
+
+### Using Metadata for Flexible Control
+
+A particularly powerful feature of access tokens is their ability to use metadata patterns for entity access control. Rather than maintaining explicit allowlists, you can tag your EOAs with descriptive metadata and then create access tokens that match specific patterns.
+
+This metadata-based approach provides tremendous flexibility in how you organize and control access to your wallet infrastructure, which is detailed further in the sections below
\ No newline at end of file
diff --git a/apps/portal/src/app/vault/key-concepts/accounts/page.mdx b/apps/portal/src/app/vault/key-concepts/accounts/page.mdx
new file mode 100644
index 00000000000..026c9f2e25d
--- /dev/null
+++ b/apps/portal/src/app/vault/key-concepts/accounts/page.mdx
@@ -0,0 +1,36 @@
+import { Callout } from "@doc";
+
+# Accounts
+
+Vault will support 2 accounts types
+
+1. User Account (*coming soon*):
+2. Service Account
+
+## User Account
+
+User accounts can be authenticated by:
+
+1. passkey
+2. SIWE
+3. OTP (email/SMS)
+4. oauth (google etc)
+
+These are meant to be owned and operated by end-users and are ideal for integrating with consumer facing applications that want to provide a web2 like blockchain experience, while still being fully non-custodial.
+
+## Service Accounts
+
+Service accounts in thirdweb Vault provide a hierarchical security model for organizational key management, combining administrative control with precise delegation capabilities. These are ideal for applications where you have programmatic access control needs for wallets, but still want to keep the system non-custodial.
+
+
+thirdweb uses vault service accounts to power engine
+
+
+### Service Account Credentials
+
+A service account has two primary credentials:
+
+1. **Admin Key**: Grants access to every operation on every entity owned by the account
+2. **Rotation Code**: Used to invalidate current credentials and generate new ones during security events
+
+Service Accounts can used in combination with access-tokens to build non-custodial programmable access control for your enterprise applications.
\ No newline at end of file
diff --git a/apps/portal/src/app/vault/key-concepts/entities/page.mdx b/apps/portal/src/app/vault/key-concepts/entities/page.mdx
new file mode 100644
index 00000000000..9db01dda458
--- /dev/null
+++ b/apps/portal/src/app/vault/key-concepts/entities/page.mdx
@@ -0,0 +1,21 @@
+# Entities
+
+Entities are the resources secured by vault. Entities are owned by a vault account.
+Vault currently secures the EOA entity.
+
+## EOA
+
+An EOA (Externally Owned Account) is an EVM account controlled by a private key held by a user. It's a fundamental part of the EVM ecosystem, used for managing funds, initiating transactions, and interacting with smart contracts.
+The private key to the EOA is always stored encrypted, and only decrypted within vault.
+
+Vault supports the following EOA related operations (API reference):
+
+```typescript
+eoa:list
+eoa:create
+eoa:signMessage
+eoa:signTypedData
+eoa:signTransaction
+eoa:signStructuredMessage
+eoa:signAuthorization
+```
diff --git a/apps/portal/src/app/vault/key-concepts/key-management/page.mdx b/apps/portal/src/app/vault/key-concepts/key-management/page.mdx
new file mode 100644
index 00000000000..1cf8d080107
--- /dev/null
+++ b/apps/portal/src/app/vault/key-concepts/key-management/page.mdx
@@ -0,0 +1,56 @@
+import { Callout } from "@doc";
+
+# Understanding Vault Keys
+
+## Vault Admin Key
+
+This is an admin key that grants access to every operation on every server wallet. It is also used to create access tokens.
+
+Keep the admin key securely and distribute it only between trusted team members (who you would consider admins, and need to perform administrative functions). Do not send this key to external services, only send it directly to vault (via E2E encryption), or use it in the thirdweb dashboard where it's always securely stored in your browser memory and only used to communicate with the vault through e2e encryption. Your admin keys are never revealed to anyone other than vault itself, and you.
+
+## Access Tokens
+
+Access Tokens are created using the admin key. Access tokens support flexible policies that allow you to restrict what it can do. It can be scoped by:
+
+1. operation type (eg signMessage or createEoa)
+2. operation payload (only allow specific types of transactions to be signed like restricting by chainId, toAddress, or max value)
+3. entity, ie, which EOAs can this access token perform operations with. Access to entities like EOAs can be scoped in 2 ways:
+ 1. **allowlist**: if you have a short list (1/2) EOAs that an access token should be able to access, you can use the allowlist
+ 2. metadata: if you have lots of entities and complex requirements for different users to access different groups of entities, you can scope by metadata. Metadata allows you to represent implicit grouping of resources and user. As an example:
+ 1. you can create multple EOAs with metadata `team: "trading-floor"`
+ 2. If you then create an access token with
+ `metadataPatterns: { key: "team", pattern: "^trading-floor$"}` ,
+ this access token will only be able to access EOAs with that specific metadata parameter set.
+ 3. This allows you to create different access tokens for different sets of EOAs, where each set is grouped together with a metadata pattern. Groups can overlap. If you want multiple groups of users with your org to have access to the same EOA, you can instead use metadata: `{ teams: "trading-floor, compliance" }`
+ And now use:
+ for trading floor:
+ `metadataPatterns: { key: "teams", pattern: "trading-floor"}`
+ for compliance:
+ `metadataPatterns: { key: "team", pattern: "compliance"}`
+
+ This is just an example of how flexible vault’s policies can be. Patterns can be regex operators or numeric comparisons. Metadata supports arbitrary key-value as well, so you can also create other metadata fields like `purpose` or `teamId` (if you want to map it to an internal team identifier)
+4. An access token can be revoked instantly with your admin key.
+5. You can share access tokens with all members of your team. There are multiple ways you should be sharing these, depending on your team and organisation structure:
+ 1. If you have distinct teams within your org that don't have overlapping needs to access EOAs, you can create team specific access tokens. Every member of a team within your org will get the same access token. If a member leaves and you want to remove their access, you can revoke the existing team access tokens, create a new access token with the same policies, and share the new token with remaining team members.
+ 2. if you have a small org, where members have large overlapping needs, you can create a single access token (scoped as minimally as possible) and share it with everyone. If a member leaves, you can revoke the existing token, create a new one, and share it with your members again.
+ 3. for the most granular permissioning, you can create a distinct access token for every member of your team with policies restricted to exactly what they need. This way the token can also be revoked individually without any side-effects to the other tokens.
+
+
+Access tokens are for using with external services or for non-adminstrative team members. Adminstrative team members might want the ability to create new access tokens, so sharing the admin key with them is more appropriate.
+
+
+## Rotation code
+
+The rotation code can be used to "rotate" your account. Rotating your account will:
+
+1. invalidate your old admin key, returning you a new key
+2. invalidate the rotation code used, returning a new rotation code
+3. invalidate all existing access tokens that were previously created.
+
+The rotation code should only be stored with the "organisation owner".
+
+It can be used in disaster scenarios when you suspect you might have leaked a key.
+
+It can also be used when an "administrative" team member who had access to your admin key leaves your org, and you want to revoke their access.
+
+After the rotation code is used, all exsting access tokens need to be recreated and shared with your team, and the newly received admin key must be shared with your "team admins".
\ No newline at end of file
diff --git a/apps/portal/src/app/engine/layout.tsx b/apps/portal/src/app/vault/layout.tsx
similarity index 68%
rename from apps/portal/src/app/engine/layout.tsx
rename to apps/portal/src/app/vault/layout.tsx
index 3b825ba3279..42d3436a83e 100644
--- a/apps/portal/src/app/engine/layout.tsx
+++ b/apps/portal/src/app/vault/layout.tsx
@@ -11,7 +11,7 @@ export default async function Layout(props: { children: React.ReactNode }) {
}
export const metadata = createMetadata({
- title: "Engine",
+ title: "Vault",
description:
- "Engine is a backend HTTP server that calls smart contracts using your managed backend wallets.",
+ "Vault is an open-source non-custodial key management service, secured with TEE architecture (AWS Nitro Enclaves) and designed for blockchain applications.",
});
diff --git a/apps/portal/src/app/vault/page.mdx b/apps/portal/src/app/vault/page.mdx
new file mode 100644
index 00000000000..05af3e32bd5
--- /dev/null
+++ b/apps/portal/src/app/vault/page.mdx
@@ -0,0 +1,51 @@
+import { createMetadata } from "@/components/Document";
+import { DocImage, FeatureCard, OpenSourceCard, Callout } from "@doc";
+import { ArrowLeftRightIcon, UserLockIcon, UsersIcon, WalletIcon } from "lucide-react";
+
+
+export const metadata = createMetadata({
+ title: "thirdweb Vault",
+ description: "An open-source, secure key management service for storing, managing, and protecting cryptographic keys and secrets.",
+});
+
+# Vault
+
+Vault is an open-source non-custodial key management service, secured with TEE architecture (AWS Nitro Enclaves) and designed for blockchain applications.
+
+## Features
+
+
+ }
+ />
+
+ }
+ />
+
+ }
+ />
+
+ }
+ />
+
+
+
+With vault, you can build applications where:
+
+- Your users never need to manage private keys
+- Your backend services can request signatures without having access to private keys
+- Your users can create controlled access for team members, services, or automation
+- Security is enforced cryptographically, not through promises
\ No newline at end of file
diff --git a/apps/portal/src/app/vault/security/page.mdx b/apps/portal/src/app/vault/security/page.mdx
new file mode 100644
index 00000000000..c3acf1df00c
--- /dev/null
+++ b/apps/portal/src/app/vault/security/page.mdx
@@ -0,0 +1,94 @@
+# Security
+
+## Non Custodiality
+
+Vault guarantees non-custodiality through cryptography. All private and sensitive data is stored encrypted, and can only be decrypted within the secure enclave. The code running within the secure enclave is open-source, audited, and attested.
+
+## Attestation
+
+At any time, you can request an attestation document from Vault. This attestation document is signed by AWS (independently verifiable).
+
+The attestation document allows you to [verify](https://aws.amazon.com/blogs/compute/validating-attestation-documents-produced-by-aws-nitro-enclaves/) that the code being run inside the secure enclave has not been tampered, and is the same as the open source code that you can access.
+
+The code running inside a nitro enclave is an Enclave Image File (EIF). The EIF has unique PCR values which will change upon tampering.
+
+In the context of AWS Nitro Enclaves, an Enclave Image File (EIF) measurement, specifically the Platform Configuration Register (PCR) values, are **cryptographic hashes that uniquely identify the enclave's image and its contents**. PCRs are used to verify that the enclave has been loaded and is running in a known, trusted state, ensuring its integrity and preventing unauthorized modification
+
+The master key of the Vault can only be accessed by this exact code running inside the enclave. To verify this, you can query Vault to check the current AWS policy on the master key, and confirm that only nitro-enclaves with this specific PCR measurement have access to these resources.
+
+## Verify, Don’t Trust
+
+You can compile your own EIF from the Vault source-code, and retrieve PCR values. This allows you to compare the PCR values you received from Vault *against* the PCR measurements you generated yourself, proving that a hosted Vault service is running untampered code.
+
+## Chain of ~~Trust~~ Verification
+
+Armed with proof that the Vault service is running untampered code, you can audit the code to ensure Vault behaves as expected.
+
+For example: how can you verify that Vault is not lying about who can access it’s keys?
+
+You can look at the Vault code to confirm that it does indeed query the correct AWS APIs to fetch the current policies on it’s keys, and then returns it without modifications.
+
+If you know the code is correct, and if you know that the service is running untampered code, then you can confirm that the correct data is being returned to you.
+
+But how can you confirm that data from the Vault hasn’t been tampered by other non-enclave components your response might be coming through? To solve this, Vault uses an end to end encrypted communication protocol with perfect forward secrecy.
+
+This same approach can be used to verify that all entities are always stored encrypted, and access is only granted to authorized requests. To further prevent data leakage, Vault uses HMAC hashes instead of raw identifiers to associate entities with each other in the encrypted database. This means Vault can not-only guarantee non-custodial access to entities, but also preserves privacy between entities and their owners. E2E encryption also means that all your operations and responses remain private and untampered.
+
+# End to End Encryption
+
+Every sensitive request to Vault is made to the `/v1/enclave/post` endpoint with a payload that looks like this:
+
+```json
+
+ {
+ "ephemeralPublicKey": "05d7deb3ef80f929ee6d1afdbf63d43e68ae9d1a045577cf6a2cbc29baaa5c5f",
+ "nonce": "716d11684ed4a973ff401e9bc84db48608c1f78abdba59a2",
+ "ciphertext": "ed0665497121ca59ef610f976f0a3beaa494c17b65ca127e72f286fa3464fde3f14e305d9fded6090bd5fd7fd2fd57d93d399619fe950d71790daec1b753d5b221d914e6e29c6734e6a38c7d237a91fea289f4812eeefae88281cc9cae8e7421ca1d81a5ac4181d889a9a082fbaf7cd5c650a2c8ccf61981d9fc3535a76733e0b00dbad4a2492c399b8a49c00f89d11283fe408754e470f5ec3579fac2aedc4c042eb75dd6804cf0fa331d5da039cfad6e36f5d00e7c6e78b5e0956a36af01761c31b0d85d90b3d15e0808a544c3f15ba1d3ae108efd36add25791ee6d27d58d9bf7c87903bbd5c54ed52c3b501eb9c67ff374308d95b7acabd7e02375fd0aab6668008583740f1883ed0c00731f732ecd4d46498939f223b1eba1c0c536cea12cf85370c17ef30fce992c129938e1f049c64c2cadafd1efc93692445c47923f6bb9ffbb8226fbf7f5bfa5a14060a2085c1df145294397a7035761c20fdac820a57ed4bdd591941a9d9804c3c92c1e5e0f60857a68516b330816c57e133b4dfcf492cdc1f9ab3d9097babd997552adbb90c871e82fbab041555f0ab4ae3fb93adf4a3ba2182d76787d58568275849595564eb10e601f7ede972f2c6d8429112f90ce4aa09177ca2811d7025100cd3621edcc8b091d2e943afdc44f91d2f60abb3daae1"
+ }
+```
+
+The communication protocol ensures that requests can only be decrypted by the Vault-enclave, and responses can only be decrypted by you. The protocol also provides perfect forward secrecy, meaning even if cryptographic keys for a previous request is exposed, future requests still remain non-compromised.
+
+## Protocol
+
+Vault uses the xChaCha20Poly1305 cryptographic cipher, combined with the x25519dalek for zero round trip key-exchange.
+
+### Step 1
+
+The client queries the Vault’s xChaCha20Poly1305 public-key from the `GET api/v1/enclave` endpoint.
+
+### Step 2
+
+The client generates a random 32 byte ephemeral secret key (and stores it to decrypt the response too)
+
+### Step 3
+
+The client derives a shared secret using xChaCha20Poly1305:
+
+```json
+shared_secret = diffie_hellman(client_ephemeral_secret_key, vault_public_key)
+```
+
+### Step 4
+
+The client derives an encryption key from the `shared_secret` using HKDF
+
+### Step 5
+
+The client generates a random 24 byte nonce
+
+The client generates the `ciphertext` using xChaCha20Poly1305 with the random nonce, and the derives encryption key
+
+### Sending the Payload
+
+The generated ciphertext, nonce, and the public key to the ephemeral secret are all hex encoded and sent as the payload
+
+## Decrypting the Response
+
+The response also arrives in the same payload format. We just perform the steps in reverse now.
+
+1. Use `x25519dalek` `diffie_hellman` to derive a `shared_secret` from the:
+ 1. private key we used for sending the request
+ 2. the public key returned in the response
+2. HKDF the `shared_secret` to get the `encryption_key`
+3. Use the `nonce` in the response (which Vault randomly generates) + the `shared_secret` with xChaCha20Poly1305 to decrypt your payload.
\ No newline at end of file
diff --git a/apps/portal/src/app/vault/sidebar.tsx b/apps/portal/src/app/vault/sidebar.tsx
new file mode 100644
index 00000000000..2160cd87285
--- /dev/null
+++ b/apps/portal/src/app/vault/sidebar.tsx
@@ -0,0 +1,66 @@
+import type { SideBar } from "@/components/Layouts/DocLayout";
+import {
+ KeyIcon,
+ MessageCircleQuestionIcon,
+ RocketIcon,
+ ShieldQuestionIcon,
+ VaultIcon,
+ WrenchIcon,
+} from "lucide-react";
+
+export const sidebar: SideBar = {
+ name: "Vault",
+ links: [
+ {
+ name: "Overview",
+ href: "/vault",
+ icon: ,
+ },
+ {
+ name: "Get Started",
+ href: "/vault/get-started",
+ icon: ,
+ },
+ {
+ name: "Key Concepts",
+ icon: ,
+ links: [
+ {
+ name: "Key Management",
+ href: "/vault/key-concepts/key-management",
+ },
+ {
+ name: "Entities",
+ href: "/vault/key-concepts/entities",
+ },
+ {
+ name: "Accounts",
+ href: "/vault/key-concepts/accounts",
+ },
+ {
+ name: "Access Tokens",
+ href: "/vault/key-concepts/access-tokens",
+ },
+ {
+ name: "Access Control",
+ href: "/vault/key-concepts/access-control",
+ },
+ ],
+ },
+ {
+ name: "Security",
+ href: "/vault/security",
+ icon: ,
+ },
+ {
+ name: "Troubleshoot",
+ href: "/vault/troubleshoot",
+ icon: ,
+ },
+ {
+ name: "FAQs",
+ href: "/vault/faqs",
+ icon: ,
+ },
+ ],
+};
diff --git a/apps/portal/src/app/vault/troubleshoot/page.mdx b/apps/portal/src/app/vault/troubleshoot/page.mdx
new file mode 100644
index 00000000000..acd5a392073
--- /dev/null
+++ b/apps/portal/src/app/vault/troubleshoot/page.mdx
@@ -0,0 +1,3 @@
+# Vault Troubleshoot Guide
+
+More information coming soon.
\ No newline at end of file
diff --git a/apps/portal/src/components/others/EngineVersionSelector.tsx b/apps/portal/src/components/others/EngineVersionSelector.tsx
new file mode 100644
index 00000000000..12d43ff254b
--- /dev/null
+++ b/apps/portal/src/components/others/EngineVersionSelector.tsx
@@ -0,0 +1,70 @@
+"use client";
+
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import clsx from "clsx";
+import { ChevronDownIcon } from "lucide-react";
+import Link from "next/link";
+
+type Version = "v2" | "v3";
+const engineLinks = [
+ {
+ name: "v2",
+ href: "/engine/v2",
+ },
+ {
+ name: "v3",
+ href: "/engine/v3",
+ },
+];
+
+export function EngineVersionSelector(props: {
+ selected: Version;
+}) {
+ // biome-ignore lint/style/noNonNullAssertion: guaranteed
+ const platform = engineLinks.find((p) => p.name === props.selected)!;
+ return (
+
+
+