### Project Setup and Run
Source: https://github.com/ithacaxyz/porto/blob/main/examples/authentication-rainbowkit/README.md
Follow these steps to clone the example project, install dependencies, configure environment variables, and start the development server.
```bash
pnpx gitpick ithacaxyz/porto/tree/main/examples/authentication-rainbowkit porto-rainbowkit && cd porto-rainbowkit
pnpm i
cp .env.example .env
pnpm dev
```
--------------------------------
### Setup and Run Porto Guest Checkout Example
Source: https://github.com/ithacaxyz/porto/blob/main/examples/guest-checkout/README.md
Clone the example repository, install dependencies using pnpm, and start the development server.
```sh
pnpx gitpick ithacaxyz/porto/tree/main/examples/guest-checkout porto-guest-checkout && cd porto-guest-checkout
pnpm i
pnpm dev
```
--------------------------------
### Setup and Run Vite React Example
Source: https://github.com/ithacaxyz/porto/blob/main/apps/playground-interop/README.md
Clone the example project, install dependencies using pnpm, and start the development server.
```sh
pnpx gitpick ithacaxyz/porto/tree/main/examples/vite-react porto-vite && cd porto-vite
pnpm i
pnpm dev
```
--------------------------------
### Project Setup and Development
Source: https://github.com/ithacaxyz/porto/blob/main/examples/authentication/README.md
Follow these commands to clone the example project, install dependencies, configure environment variables, and start the development server.
```bash
pnpx gitpick ithacaxyz/porto/tree/main/examples/authentication porto-auth && cd porto-auth
pnpm i
cp .env.example .env
pnpm dev
```
--------------------------------
### Setup and Run Porto Theming Example
Source: https://github.com/ithacaxyz/porto/blob/main/examples/theming/README.md
Use these commands to clone the Porto theming example, install dependencies, and start the development server.
```sh
pnpx gitpick ithacaxyz/porto/tree/main/examples/theming porto-theming && cd porto-theming
pnpm i
pnpm dev
```
--------------------------------
### Setup Porto Payments Project
Source: https://github.com/ithacaxyz/porto/blob/main/examples/payments/README.md
Clone the Porto payments example, install dependencies, and start the development server.
```sh
pnpx gitpick ithacaxyz/porto/tree/main/examples/payments porto-payments && cd porto-payments
pnpm i
pnpm dev
```
--------------------------------
### Project Setup and Initialization
Source: https://github.com/ithacaxyz/porto/blob/main/examples/authentication-better-auth/README.md
Follow these commands to clone the project, install dependencies, configure environment variables, generate the database schema, and start the development server.
```sh
pnpx gitpick ithacaxyz/porto/tree/main/examples/authentication-better-auth porto-better-auth && cd porto-better-auth
```
```sh
pnpm i
```
```sh
cp .env.example .env
```
```sh
pnpm db:generate
```
```sh
pnpm dev
```
--------------------------------
### Setup Project
Source: https://github.com/ithacaxyz/porto/blob/main/examples/sponsoring-vite/README.md
Use this command to clone the example project and navigate into its directory.
```sh
pnpx gitpick ithacaxyz/porto/tree/main/examples/sponsoring-vite porto-sponsoring && cd porto-sponsoring
```
--------------------------------
### Setup and Run Dynamic Porto Project
Source: https://github.com/ithacaxyz/porto/blob/main/examples/dynamic/README.md
Use these commands to clone the dynamic Porto example, install its dependencies, and start the development server.
```sh
pnpx gitpick ithacaxyz/porto/tree/main/examples/dynamic porto-dynamic && cd porto-dynamic
```
```sh
pnpm i
```
```sh
pnpm dev
```
--------------------------------
### Project Setup and Initialization
Source: https://github.com/ithacaxyz/porto/blob/main/examples/react-native-relay-mode/README.md
Use these commands to clone the example project and set up the environment variables.
```sh
pnpx gitpick ithacaxyz/porto/tree/main/examples/react-native-relay-mode porto-react-native-relay-app && cd porto-react-native-relay-app
cp .env.example .env
```
--------------------------------
### Install and Run Porto CLI Example
Source: https://github.com/ithacaxyz/porto/blob/main/examples/cli/README.md
Installs the Porto CLI from a specific Git branch, navigates into the project directory, installs dependencies, links the package, and then runs the example CLI command.
```sh
pnpx gitpick ithacaxyz/porto/tree/main/examples/cli porto-cli && cd porto-cli
pnpm i
pnpm link
example-cli
```
--------------------------------
### Install Dependencies and Run Dev Server
Source: https://github.com/ithacaxyz/porto/blob/main/apps/dialog/README.md
Run these commands from the project root to install dependencies and start the development server.
```sh
pnpm i
pnpm dev
```
--------------------------------
### Install Dependencies and Run Development Server
Source: https://github.com/ithacaxyz/porto/blob/main/apps/id/README.md
Run these commands from the project root to install dependencies and start the development server for the ID application.
```sh
pnpm i
pnpm dev:id
```
--------------------------------
### Setup React Native Project
Source: https://github.com/ithacaxyz/porto/blob/main/examples/react-native/README.md
Use this command to clone the React Native example project and navigate into its directory.
```sh
pnpx gitpick ithacaxyz/porto/tree/main/examples/react-native porto-react-native-app && cd porto-react-native-app
```
--------------------------------
### Install and Run Porto Apps
Source: https://github.com/ithacaxyz/porto/blob/main/README.md
Installs project dependencies and starts the id, playground, and iframe dialog for Porto applications. Use this for local development.
```bash
pnpm install
pnpm dev
```
--------------------------------
### Example: Prepare EOA Upgrade
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/rpc/wallet_prepareUpgradeAccount.mdx
Demonstrates how to call `wallet_prepareUpgradeAccount` to get the necessary context and digests for upgrading an EOA, and then signing them with the EOA.
```typescript
import { Porto } from 'porto'
import { privateKeyToAccount } from 'viem/accounts'
const { provider } = Porto.create()
const eoa = privateKeyToAccount('0x...')
const { context, digests } = await provider.request ({
method: 'wallet_prepareUpgradeAccount', // [!code focus]
params: [{
address: eoa.address, // [!code focus]
}], // [!code focus]
}) // [!code focus]
const signatures = {
auth: await eoa.sign({ hash: digests.auth }),
exec: await eoa.sign({ hash: digests.exec }),
} as const
const response = await provider.request({
method: 'wallet_upgradeAccount',
params: [{
context,
signatures,
}],
})
```
--------------------------------
### Porto CLI for Merchant Onboarding
Source: https://context7.com/ithacaxyz/porto/llms.txt
Use the Porto CLI to onboard new merchant accounts and manage credentials. This example shows how to install and run the CLI, onboard an account on the testnet, and set up environment variables.
```bash
# Install and run via npx
npx porto --help
# Onboard a new merchant account on testnet
npx porto onboard --admin-key --testnet
# Output:
# MERCHANT_ADDRESS=0x...
# MERCHANT_PRIVATE_KEY=0x...
# Place credentials in .env
echo "MERCHANT_ADDRESS=0x..." >> .env
echo "MERCHANT_PRIVATE_KEY=0x..." >> .env
```
--------------------------------
### Get Wallet Capabilities using Porto SDK
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/rpc/wallet_getCapabilities.mdx
Demonstrates how to use the Porto SDK to request wallet capabilities. This example shows the basic call to the provider to get the supported features of the wallet.
```typescript
import { Porto } from 'porto'
const { provider } = Porto.create()
const capabilities = await provider.request({
method: 'wallet_getCapabilities',
})
```
--------------------------------
### Wagmi Configuration Example
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/wagmi/getAssets.mdx
This snippet shows a typical configuration setup for Wagmi, which is required for using actions like getAssets.
```typescript
// [!include ~/snippets/wagmi/config.ts]
```
--------------------------------
### Install Foundry and Build Contracts
Source: https://github.com/ithacaxyz/porto/blob/main/README.md
Installs the Foundry toolchain and builds the smart contracts for the account and demo modules. Ensure Foundry is installed before running.
```bash
# Install Foundry
foundryup
forge build --config-path ./contracts/account/foundry.toml # Build
forge test --config-path ./contracts/account/foundry.toml # Test
forge build --config-path ./contracts/demo/foundry.toml # Build
forge test --config-path ./contracts/demo/foundry.toml # Test
```
--------------------------------
### Basic Wallet Connect Example
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/rpc/wallet_connect.mdx
A basic example demonstrating how to initiate a wallet connection using the provider.request method with the 'wallet_connect' method.
```typescript
import { Porto } from 'porto'
const { provider } = Porto.create()
const response = await provider.request({
method: 'wallet_connect',
})
```
--------------------------------
### Clone and Navigate Project
Source: https://github.com/ithacaxyz/porto/blob/main/examples/sponsoring-privy/README.md
Use this command to clone the example project and navigate into its directory.
```sh
pnpx gitpick ithacaxyz/porto/tree/main/examples/sponsoring-privy porto-sponsoring-privy && cd porto-sponsoring-privy
```
--------------------------------
### Example: Sending Prepared Calls with wallet_sendPreparedCalls
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/rpc/wallet_sendPreparedCalls.md
Demonstrates how to prepare calls using wallet_prepareCalls, sign the digest, and then send the prepared calls with the signature using wallet_sendPreparedCalls. This example utilizes WebCryptoP256 for key pair generation and signing.
```typescript
import { Porto } from 'porto'
import { PublicKey, Signature, WebCryptoP256 } from 'ox'
const { provider } = Porto.create()
const { publicKey, privateKey } = await WebCryptoP256.createKeyPair()
const { digest, ...request } = await provider.request({
method: 'wallet_prepareCalls',
params: [{
calls: [{
to: '0xcafebabecafebabecafebabecafebabecafebabe',
value: '0x12345678',
}],
key: {
publicKey: PublicKey.toHex(publicKey),
type: 'p256'
}
}]
})
const signature = await WebCryptoP256.sign({
payload: digest,
privateKey,
})
const response = await provider.request({
method: 'wallet_sendPreparedCalls',
params: [{
...request,
signature: Signature.toHex(signature)
}]
})
```
--------------------------------
### Clone and Navigate Project
Source: https://github.com/ithacaxyz/porto/blob/main/examples/sponsoring-next.js/README.md
Use this command to clone the example project and navigate into its directory.
```sh
pnpx gitpick ithacaxyz/porto/tree/main/examples/sponsoring-next.js porto-sponsoring && cd porto-sponsoring
```
--------------------------------
### Install and Run Porto Tests
Source: https://github.com/ithacaxyz/porto/blob/main/README.md
Installs project dependencies and runs the test suite for Porto. Use this to verify the integrity of the project.
```bash
pnpm install
pnpm test
```
--------------------------------
### Install Porto SDK with NPM, PNPM, or BUN
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/index.mdx
Install the Porto SDK using your preferred package manager.
```bash
npm i porto
```
```bash
pnpm i porto
```
```bash
bun i porto
```
--------------------------------
### Clone Sponsoring Next.js Example
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/guides/sponsoring.mdx
Use this command to clone the Next.js-based example for fee sponsoring.
```bash
pnpx gitpick ithacaxyz/porto/tree/main/examples/sponsoring-next.js
```
--------------------------------
### Clone and Run Next.js Project
Source: https://github.com/ithacaxyz/porto/blob/main/examples/next.js/README.md
Use these commands to clone a Next.js project from a GitHub repository, install its dependencies using pnpm, and start the development server.
```sh
pnpx gitpick ithacaxyz/porto/tree/main/examples/next.js porto-next && cd porto-next
pnpm i
pnpm dev
```
--------------------------------
### Install Dependencies
Source: https://github.com/ithacaxyz/porto/blob/main/examples/react-native-relay-mode/README.md
Installs all necessary project dependencies using pnpm.
```sh
pnpm i
```
--------------------------------
### Clone Sponsoring Vite Example
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/guides/sponsoring.mdx
Use this command to clone the Vite-based example for fee sponsoring.
```bash
pnpx gitpick ithacaxyz/porto/tree/main/examples/sponsoring-vite
```
--------------------------------
### Example: Requesting Wallet Connect with Grant Permissions
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/rpc/capabilities.mdx
This example demonstrates how to structure a `wallet_connect` request that includes the `grantPermissions` capability, specifying expiry, fee token, and detailed call and spend permissions.
```typescript
// @noErrors
const capabilities = await provider.request({
method: 'wallet_connect',
params: [{
capabilities: { // [!code focus]
grantPermissions: { // [!code focus]
expiry: 1727078400, // [!code focus]
feeToken: { // [!code focus]
limit: '1', // [!code focus]
symbol: 'USDC', // [!code focus]
}, // [!code focus]
permissions: { // [!code focus]
calls: [{ signature: 'subscribe()' }], // [!code focus]
spend: [{ // [!code focus]
limit: '0x5f5e100', // 100 USDC // [!code focus]
period: 'day', // [!code focus]
token: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC // [!code focus]
}] // [!code focus]
} // [!code focus]
},
}, // [!code focus]
/* ... */
}]
})
```
--------------------------------
### Run Server - Development
Source: https://github.com/ithacaxyz/porto/blob/main/examples/react-native-relay-mode/README.md
Starts the server in development mode with hot-reloading.
```sh
bun --watch --hot ./server/index.ts --env-file .env
```
--------------------------------
### Execution Example
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/contracts/account.md
Example demonstrating how to construct and execute a batch of calls from an arbitrary sender.
```APIDOC
## Example
```solidity
Call memory call = Call({
to:
,
value: 0,
data:
});
uint256 nonce = account.getNonce(0); // 0 is the uint192 sequence key
bytes memory signature = _sign(computeDigest(calls, nonce));
bytes memory opData = abi.encodePacked(nonce, signature);
bytes memory executionData = abi.encode(calls, opData);
account.execute(_ERC7821_BATCH_EXECUTION_MODE, executionData);
```
```
--------------------------------
### Start Development Environment with Anvil
Source: https://github.com/ithacaxyz/porto/blob/main/apps/playground/README.md
Use this command to start the local Anvil blockchain environment for development and testing.
```bash
pnpm dev:anvil
```
--------------------------------
### TryItOut Example for wallet_getCallsHistory
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/wagmi/useCallsHistory.mdx
This example demonstrates how to use the TryItOut component to interact with the wallet_getCallsHistory RPC method. It requests accounts, fetches the call history, and transforms the result for display.
```javascript
async ({ provider }) => {
const [address] = await provider.request({ method: 'eth_requestAccounts' })
return provider.request({
method: 'wallet_getCallsHistory',
params: [{
address,
limit: 5,
sort: 'desc',
}],
})
}
```
```javascript
(code) => {
return 'const history = ' + code
}
```
--------------------------------
### Example JSON Response for wallet_getCapabilities
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/relay/wallet_getCapabilities.md
An example of the JSON response returned by the `wallet_getCapabilities` method, detailing contract addresses and fee information for a specific chain.
```json
{
"0x14a34": {
"contracts": {
"orchestrator": {
"address": "0xb447ba5a2fb841406cdac4585fdc28027d7ae503",
"version": "0.4.6"
},
"accountImplementation": {
"address": "0xc4e1dc6045234b913db45e8f51e770d6d12e42a1",
"version": "0.4.11"
},
"legacyOrchestrators": [],
"legacyAccountImplementations": [],
"accountProxy": {
"address": "0x5874f358359ee96d2b3520409018f1a6f59a2cdc",
"version": null
},
"simulator": {
"address": "0xcb80788813c39d90c48c2733b43b3e47e23a2d3f",
"version": null
},
"funder": {
"address": "0x665efbf4b831aac6b712471c6bbfdb11e1721b4f",
"version": null
},
"escrow": {
"address": "0x55626138525a47af075322aafe1df8f68993b11d",
"version": null
}
},
"fees": {
"recipient": "0x665efbf4b831aac6b712471c6bbfdb11e1721b4f",
"quoteConfig": {
"constantRate": null,
"gas": {
"intentBuffer": 20000,
"txBuffer": 10000
},
"ttl": 30,
"rateTtl": 300
},
"tokens": [
{
"uid": "exp2",
"address": "0x2ace05bcb50b49953aaa4c00f318db908a512d99",
"decimals": 18,
"feeToken": true,
"interop": true,
"symbol": "EXP2",
"nativeRate": "0xc536acbc02a4"
},
{
"uid": "exp1",
"address": "0x74e294e9d05bace256796040ca6dc0c47efb9fff",
"decimals": 18,
"feeToken": true,
"interop": true,
"symbol": "EXP",
"nativeRate": "0xc536acbc02a4"
},
{
"uid": "teth",
"address": "0x0000000000000000000000000000000000000000",
"decimals": 18,
"feeToken": true,
"interop": true,
"symbol": "ETH",
"nativeRate": "0xde0b6b3a7640000"
}
]
}
}
}
```
--------------------------------
### prepareUpgradeAccount Usage
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/viem/RelayActions/prepareUpgradeAccount.mdx
Demonstrates how to use the `prepareUpgradeAccount` function with an example.
```APIDOC
## `prepareUpgradeAccount`
### Description
Prepares an EOA to be upgraded to a Porto Account.
### Method Signature
`prepareUpgradeAccount(client, parameters)`
### Parameters
#### `client`
- **Type:** `Viem Client`
- **Description:** The Viem client instance.
#### `parameters`
- **Type:** `object`
- **`address`** (`Address.Address`) - Required - Address of the EOA account to upgrade.
- **`authorizeKeys`** (`readonly Key.Key[]`) - Required - Keys to authorize on the upgraded account.
- **`delegation`** (`Address.Address`) - Optional - Contract address to delegate to. Defaults to the account proxy contract.
- **`feeToken`** (`'native' | Token.Symbol | Address.Address`) - Optional - Token to use to cover fees. Accepts:
- `"native"` (Default): The native token of the chain.
- Symbol: Symbol of the fee token (e.g. `"USDC"`).
- Address: Address of the fee token (e.g. `"0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"`).
### Returns
See [`wallet_prepareUpgradeAccount`](/relay/wallet_prepareUpgradeAccount#response).
### Example
```ts
import { RelayActions, Key } from 'porto/viem'
import { client } from './config'
const adminKey = Key.createSecp256k1({ role: 'admin' })
const prepared = await RelayActions.prepareUpgradeAccount(client, {
address: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
authorizeKeys: [adminKey],
})
```
```
--------------------------------
### Example Usage of eth_requestAccounts
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/rpc/eth_requestAccounts.mdx
Demonstrates how to use the eth_requestAccounts method with a provider to get connected account addresses. Ensure you have Porto initialized.
```typescript
import { Porto } from 'porto'
const { provider } = Porto.create()
const accounts = await provider.request({ method: 'eth_requestAccounts' }) // [!code focus]
```
--------------------------------
### Get Assets for an Account - Wagmi
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/wagmi/getAssets.mdx
Use Actions.getAssets to retrieve assets for an account. Ensure you have the config object imported from your wagmi setup.
```typescript
import { Actions } from 'porto/wagmi'
import { config } from './config'
const assets = await Actions.getAssets(config, {
account: '0x...',
})
```
--------------------------------
### Get Account Assets
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/rpc/wallet_getAssets.mdx
This example demonstrates how to request assets for an account. It first requests account authorization and then calls `wallet_getAssets` with the account address.
```typescript
import { Porto } from 'porto'
const { provider } = Porto.create()
const [account] = await provider.request({ method: 'eth_requestAccounts' })
const assets = await provider.request({
method: 'wallet_getAssets',
params: [{ account }],
})
```
--------------------------------
### Initialize Porto with Viem Wallet Client
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/index.mdx
Set up a Viem Wallet Client using Porto's provider for interacting with Viem Wallet Actions.
```typescript
import { custom, createWalletClient } from 'viem'
import { baseSepolia } from 'viem/chains'
import { Porto } from 'porto'
// 1. Initialize Porto.
const porto = Porto.create()
// 2. Initialize Wallet Client.
const walletClient = createWalletClient({
chain: baseSepolia,
transport: custom(porto.provider),
})
// 3. Use Wallet Actions.
const addresses = await walletClient.requestAddresses()
```
--------------------------------
### Next.js Router Integration
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/api/router.mdx
Integrate the Porto router into a Next.js application using the App Router. This example sets up routes for GET, OPTIONS, and POST requests.
```typescript
import { Router, Route } from 'porto/server'
const porto = Router({ basePath: '/porto' })
.route('/merchant', Route.merchant({ /* ... */ })
// .route('/auth', Route.auth({/* ... */}) 🚧
// .route('/rpc', Route.relay({/* ... */}) 🚧
)
export const GET = porto.fetch
export const OPTIONS = porto.fetch
export const POST = porto.fetch
```
--------------------------------
### Get Relay Capabilities with Viem
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/viem/RelayActions/getCapabilities.mdx
Import and use the `getCapabilities` action from `porto/viem` with your Viem client. Ensure your client configuration is set up correctly, as shown in the `config.ts` example.
```typescript
import { RelayActions } from 'porto/viem'
import { client } from './config'
const capabilities = await RelayActions.getCapabilities(client) // [!code focus]
```
```typescript
// [!include ~/snippets/viem/config.server.ts]
```
--------------------------------
### Broadcasting Prepared Calls with Viem RelayActions
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/viem/RelayActions/sendPreparedCalls.mdx
This example demonstrates how to create an account, prepare calls, sign the digest, and then send the prepared calls using `RelayActions.sendPreparedCalls`. Ensure you have the necessary imports and client configuration.
```typescript
import { RelayActions, Key } from 'porto/viem'
import { parseEther } from 'viem'
import { client } from './config'
// Create (or import) account
const key = Key.createP256()
const account = await RelayActions.createAccount(client, {
authorizeKeys: [key],
})
// Prepare the calls
const request = await RelayActions.prepareCalls(client, {
account,
calls: [{
to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8',
value: parseEther('0.01'),
}],
key,
})
// Sign the digest // [!code focus]
const signature = await RelayActions.signCalls(request, { key }) // [!code focus]
// Send the prepared calls // [!code focus]
const result = await RelayActions.sendPreparedCalls(client, { // [!code focus]
...request, // [!code focus]
signature, // [!code focus]
}) // [!code focus]
```
```typescript
// [!include ~/snippets/viem/config.server.ts]
```
--------------------------------
### SimpleSettler Usage Examples
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/contracts/interop/settlement.mdx
Demonstrates how to use SimpleSettler for direct owner-initiated settlements or permissionless settlements using EIP-712 signatures, and how to verify settlement status.
```solidity
// Owner directly writes settlement
simpleSettler.write(senderAddress, settlementId, chainId);
// Or use signature for permissionless settlement
bytes memory signature = signSettlement(sender, settlementId, chainId);
simpleSettler.write(sender, settlementId, chainId, signature);
// Verify settlement
bool isSettled = simpleSettler.read(settlementId, sender, chainId);
```
--------------------------------
### Install Dependencies with pnpm
Source: https://github.com/ithacaxyz/porto/blob/main/CLAUDE.md
Use this command to install all project dependencies using pnpm.
```bash
pnpm install # Install dependencies
```
--------------------------------
### Instantiate Session Key with Permissions
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/viem/Key/fromWebCryptoP256.mdx
This example shows how to create a session key with specific permissions, including call restrictions and spending limits.
```APIDOC
## Key.fromWebCryptoP256
Instantiates a WebCryptoP256 key from existing WebCrypto key pair parameters.
### Usage
#### Session Key with Permissions
```ts
import { Key } from 'porto/viem'
import { WebCryptoP256 } from 'ox'
import { parseEther } from 'viem'
const keyPair = await WebCryptoP256.createKeyPair()
const key = Key.fromWebCryptoP256({
expiry: Math.floor(Date.now() / 1000) + 60 * 60, // 1 hour
keyPair,
permissions: {
calls: [{
signature: 'transfer(address,uint256)',
to: '0xaf3b0a5b4becc4fa1dfafe74580efa19a2ea49fa',
}],
spend: [{
limit: parseEther('50'), // 50 EXP
period: 'day',
token: '0xaf3b0a5b4becc4fa1dfafe74580efa19a2ea49fa',
}],
},
role: 'session',
})
```
### Parameters
#### expiry
- **Type:** `number | undefined`
The expiry timestamp of the key (Unix timestamp). Defaults to 0 (never expires).
#### keyPair
- **Type:** `KeyPair`
WebCrypto P256 key pair (required).
```ts
type KeyPair = {
/** Web Crypto private key */
privateKey: CryptoKey
/** Web Crypto public key */
publicKey: CryptoKey
}
```
#### permissions
The permissions associated with the key.
```ts
type Permissions = {
/** Call permissions - which functions the key can call */
calls?: {
/** Function signature or 4-byte selector */
signature?: string | undefined
/** Target contract address */
to?: `0x${string}` | undefined
}[] | undefined
/** Spend permissions - spending limits for tokens */
spend?: {
/** Spending limit per period (in wei) */
limit: `0x${string}`
/** Time period for the spending limit */
period: 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year'
/** ERC20 token address (defaults to native token if not provided) */
token?: `0x${string}` | undefined
}[] | undefined
}
```
#### role
- **Type:** `"admin" | "session" | undefined`
The role of the key. Defaults to 'admin'.
### Return Value
```ts
type WebCryptoKey = {
/** Key expiry timestamp */
expiry: number
/** Key hash identifier */
hash: `0x${string}`
/** Key ID (lowercase public key) */
id: `0x${string}`
/** Optional permissions */
permissions?: Permissions | undefined
/** Whether the key requires prehashing (always true for WebCrypto) */
prehash: true
/** Web Crypto private key */
privateKey: CryptoKey
/** Public key (64 bytes, uncompressed, without 0x04 prefix) */
publicKey: `0x${string}`
/** Key role */
role: 'admin' | 'session'
/** Key type - always 'p256' (reuses P256 type with WebCrypto backend) */
type: 'p256'
}
```
```
--------------------------------
### Example Usage of wallet_upgradeAccount
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/rpc/wallet_upgradeAccount.mdx
Demonstrates how to use `wallet_upgradeAccount` after preparing the upgrade with `wallet_prepareUpgradeAccount`. This involves obtaining context and digests, signing them, and then sending the upgrade request.
```typescript
import { Porto } from 'porto'
import { privateKeyToAccount } from 'viem/accounts'
const { provider } = Porto.create()
const eoa = privateKeyToAccount('0x...')
const { context, digests } = await provider.request({
method: 'wallet_prepareUpgradeAccount',
params: [{
address: eoa.address,
}],
})
const signatures = {
auth: await eoa.sign({ hash: digests.auth }),
exec: await eoa.sign({ hash: digests.exec }),
} as const
const response = await provider.request({ // [!code focus]
method: 'wallet_upgradeAccount', // [!code focus]
params: [{
context, // [!code focus]
signatures, // [!code focus]
}], // [!code focus]
}) // [!code focus]
```
--------------------------------
### Start Development Server with Tunnel
Source: https://github.com/ithacaxyz/porto/blob/main/examples/react-native/README.md
Starts the development server with a tunnel, useful for remote debugging or testing.
```sh
pnpm expo start --dev-client --tunnel --clear
```
--------------------------------
### Install vite-plugin-mkcert for Vite HTTPS
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/index.mdx
Install the vite-plugin-mkcert package to enable HTTPS on Vite's development server.
```bash
npm i vite-plugin-mkcert
```
--------------------------------
### Example Request for Base Sepolia using `cast`
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/relay/wallet_addFaucetFunds.md
Demonstrates how to use the `cast` command-line tool to request faucet funds for the Base Sepolia testnet. Ensure to replace placeholders with actual values.
```bash
cast rpc --rpc-url https://rpc.porto.sh \
wallet_addFaucetFunds '[{"address":"0xYourAddress","chainId":84532,"tokenAddress":"0x3a9b126bf65c518f1e02602bd77bd1288147f94c","value":25}]' --raw
```
--------------------------------
### Batch Execution Example
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/contracts/account.md
Demonstrates how to construct and execute a batch of calls from an arbitrary sender. It involves signing the calls with a nonce and then encoding the calls and opData for the `execute` function.
```solidity
Call memory call = Call({
to: ,
value: 0,
data:
});
uint256 nonce = account.getNonce(0); // 0 is the uint192 sequence key
bytes memory signature = _sign(computeDigest(calls, nonce));
bytes memory opData = abi.encodePacked(nonce, signature);
bytes memory executionData = abi.encode(calls, opData);
account.execute(_ERC7821_BATCH_EXECUTION_MODE, executionData);
```
--------------------------------
### Complete Cross-Chain Trade Integration Example
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/contracts/interop/settlement.mdx
Demonstrates the steps for executing a complete cross-chain trade using LayerZeroSettler, including escrow creation, sending settlement, and final settlement confirmation.
```solidity
// 1. Create escrow with LayerZeroSettler
Escrow memory escrowData = Escrow({
settler: address(layerZeroSettler),
settlementId: tradeId,
senderChainId: 137, // Expecting from Polygon
// ... other fields
});
// 2. On source chain (Polygon): Send settlement
layerZeroSettler.send(tradeId, abi.encode([1])); // To Ethereum
layerZeroSettler.executeSend{value: fee}(
orchestrator,
tradeId,
abi.encode([1])
);
// 3. On destination chain: Settlement auto-recorded via _lzReceive
// 4. Settle the escrow
escrow.settle([escrowId]); // Automatically verified with settler
```
--------------------------------
### Instantiate Key from WebCrypto Key Pair
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/viem/Key/fromWebCryptoP256.mdx
This example demonstrates how to create a `Key` instance using an existing WebCrypto P256 key pair.
```APIDOC
## Key.fromWebCryptoP256
Instantiates a WebCryptoP256 key from existing WebCrypto key pair parameters.
### Usage
#### From WebCrypto Key Pair
```ts
import { Key } from 'porto/viem'
import { WebCryptoP256 } from 'ox'
const keyPair = await WebCryptoP256.createKeyPair()
const key = Key.fromWebCryptoP256({
keyPair,
})
```
### Parameters
#### keyPair
- **Type:** `KeyPair`
WebCrypto P256 key pair (required).
```ts
type KeyPair = {
/** Web Crypto private key */
privateKey: CryptoKey
/** Web Crypto public key */
publicKey: CryptoKey
}
```
### Return Value
```ts
type WebCryptoKey = {
/** Key expiry timestamp */
expiry: number
/** Key hash identifier */
hash: `0x${string}`
/** Key ID (lowercase public key) */
id: `0x${string}`
/** Optional permissions */
permissions?: Permissions | undefined
/** Whether the key requires prehashing (always true for WebCrypto) */
prehash: true
/** Web Crypto private key */
privateKey: CryptoKey
/** Public key (64 bytes, uncompressed, without 0x04 prefix) */
publicKey: `0x${string}`
/** Key role */
role: 'admin' | 'session'
/** Key type - always 'p256' (reuses P256 type with WebCrypto backend) */
type: 'p256'
}
```
```
--------------------------------
### eth_sendTransaction Example
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/rpc/eth_sendTransaction.mdx
This example demonstrates how to send a basic transaction using eth_sendTransaction. Ensure you have the Porto SDK initialized and a provider available.
```typescript
import { Porto } from 'porto'
const { provider } = Porto.create()
const hash = await provider.request({
method: 'eth_sendTransaction',
params: [{
from: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
to: '0xcafebabecafebabecafebabecafebabecafebabe',
value: '0x1',
}],
})
```
--------------------------------
### Example: Using Permissions Capability in `wallet_sendCalls`
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/rpc/capabilities.mdx
This example shows how to include the `permissions` capability in a `wallet_sendCalls` request, referencing a specific permission ID.
```typescript
// @noErrors
const capabilities = await provider.request({
method: 'wallet_sendCalls',
params: [{
capabilities: { // [!code focus]
permissions: { // [!code focus]
id: '0x...', // [!code focus]
}, // [!code focus]
}, // [!code focus]
/* ... */
}]
})
```
--------------------------------
### Build and Run Development Servers
Source: https://github.com/ithacaxyz/porto/blob/main/CLAUDE.md
Commands for building the core library and running development servers for the playground, dialog, and id services. Includes options for running with local Relay and Anvil services, or with the wagmi playground.
```bash
pnpm build # Build the core library
pnpm dev # Link library & run dev servers (playground, dialog, id)
pnpm dev:anvil # Run `pnpm dev` with local Relay and Anvil services
pnpm dev:wagmi # Run `pnpm dev` with wagmi playground
```
--------------------------------
### Sign In with Ethereum
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/wagmi/connect.mdx
This example shows how to use `Actions.connect` with the `signInWithEthereum` parameter to enable Sign-In with Ethereum (ERC-4361) authentication.
```APIDOC
## Actions.connect with Sign In with Ethereum
### Parameters
#### signInWithEthereum
`SignInWithEthereum` [ERC-4361](https://eips.ethereum.org/EIPS/eip-4361) Sign-In with Ethereum options.
```ts
type SignInWithEthereum = {
/* Required fields */
authUrl: string | {
logout: string
nonce: string
verify: string
}
// OR
nonce: string
/* Optional fields */
chainId?: number | undefined
domain?: string | undefined // Defaults to window/iframe parent
expirationTime?: Date | undefined
issuedAt?: Date | undefined
notBefore?: Date | undefined
requestId?: string | undefined
resources?: string[] | undefined
scheme?: string | undefined
statement?: string | undefined
uri?: string | undefined // Defaults to window/iframe parent
version?: '1' | undefined
}
```
```
--------------------------------
### Connect Account with Permissions
Source: https://github.com/ithacaxyz/porto/blob/main/apps/docs/pages/sdk/wagmi/connect.mdx
This example shows how to use `Actions.connect` with the `grantPermissions` parameter to allow the application to perform actions on behalf of the account.
```APIDOC
## Actions.connect with Grant Permissions
### Grant Permissions
You can grant permissions for an application to perform actions on behalf of the account by providing the `grantPermissions` parameter.
```ts
import { Actions } from 'porto/wagmi'
import { porto } from 'wagmi/connectors'
import { parseEther, toHex } from 'viem'
import { config } from './config'
const token = '0xaf3b0a5b4becc4fa1dfafe74580efa19a2ea49fa'
const result = await Actions.connect(config, {
connector: porto(),
grantPermissions: {
expiry: Math.floor(Date.now() / 1_000) + 60 * 60, // 1 hour
permissions: {
calls: [{
signature: 'transfer(address,uint256)',
to: token,
}],
spend: [{
limit: toHex(parseEther('50')), // 50 EXP
period: 'day',
token: token,
}],
},
},
})
```
### Parameters
#### grantPermissions
`Permissions` to grant to the account.
```ts
type GrantPermissions = {
/** Expiry timestamp for the permissions */
expiry: number
/**
* Fee token that will be used with these permissions.
*/
feeToken: {
/** Value of the limit in the symbols's unit (e.g. '1' = 1 USDC). */
limit: string
/** Symbol of the fee token. `undefined` for native token. */
symbol?: Token.Symbol | undefined
} | undefined,
/** Key to grant permissions to. Defaults to a wallet-managed key. */
key?: {
/** Public key. Accepts an address for `address` & `secp256k1` types. */
publicKey?: `0x${string}`
/** Key type. */
type?: 'address' | 'p256' | 'secp256k1' | 'webauthn-p256'
}
/** Permissions to grant */
permissions: {
/** Call permissions */
calls: {
/** Function signature or 4-byte signature */
signature?: string
/** Authorized target address */
to?: `0x${string}`
}[]
/** Spend permissions */
spend: {
/** Spending limit (in wei) per period */
limit: `0x${string}`
/** Period of the spend limit */
period: 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year'
/** ERC20 token to set the limit on (defaults to native token) */
token?: `0x${string}`
}[]
}
}
```
```