Capabilities
Porto supports EIP-5792 Capabilities.
Capabilites are extension features that allow for extra functionality to be requested on particular JSON-RPC requests such as wallet_connect
and wallet_sendCalls
, and also enable additional JSON-RPC methods. Such features could be requesting to grant permissions on connection, or setting a custom fee token.
Porto supports the following capabilities:
Capability | Description | Standard |
---|---|---|
feeToken | Indicates if custom fee tokens are supported. | Experimental |
merchant | Indicates if merchant functionality is supported. | Experimental |
permissions | Indicates if permissions can be requested by the app. | Experimental |
signInWithEthereum | Adds support for ERC-4361 Sign in with Ethereum. | Experimental |
Fee Tokens
Porto allows for an application developer to use custom fee (gas) tokens to pay for the execution of a call bundle.
Custom fee tokens are indicated by the feeToken
capability on wallet_getCapabilities
Discovery
Tokens can be discovered by the application via feeToken.tokens
on the wallet_getCapabilities
method.
import { Porto } from 'porto'
const { provider } = Porto.create()
const capabilities = await provider.request({
method: 'wallet_getCapabilities',
})
const tokens = Object.values(capabilities)[0].feeToken.tokens
Request Capabilities
feeToken
Custom fee token to use for the request.
The following JSON-RPC methods support the feeToken
request capability:
type Capability = {
/** Custom fee token address. */
feeToken: `0x${string}`
}
Example
const capabilities = await provider.request({
method: 'wallet_sendCalls',
params: [{
capabilities: {
feeToken: '0x036cbd53842c5426634e7929541ec2318f3dcf7e', // USDC
},
/* ... */
}]
})
permissions
Porto supports account permission management.
Methods
The permissions
capability enables the following methods:
Request Capabilities
grantPermissions
Requests for the wallet to grant permissions.
The following JSON-RPC methods support the grantPermissions
request capability:
type Capability = {
/** Requests for the wallet to grant these permissions. */
grantPermissions: {
/** Expiry of the permissions. */
expiry: number
/**
* Limit that the key can spend on fees. When provided,
* Porto will assign a spend permission on the user's
* selected fee token that is equal to the limit provided.
*/
feeLimit?: {
/** Currency of the limit. */
currency: 'ETH' | 'USD' | 'USDC' | 'USDT'
/** Value of the limit in the currency's unit (e.g. '1' = 1 USDC). */
value: string
} | 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. */
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.
* If not provided, the limit will be set on the
* native token (e.g. ETH).
*/
token?: `0x${string}`
}[],
}
},
}
Example
const capabilities = await provider.request({
method: 'wallet_connect',
params: [{
capabilities: {
grantPermissions: {
expiry: 1727078400,
feeLimit: {
currency: 'USD',
value: '1',
},
permissions: {
calls: [{ signature: 'subscribe()' }],
spend: [{
limit: '0x5f5e100', // 100 USDC
period: 'day',
token: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC
}]
}
},
},
/* ... */
}]
})
permissions
Use a provided permission for the request.
The following JSON-RPC methods support the permissions
request capability:
type Capability = {
/** Permission to use for the request. */
permissions: {
/** ID of the permission to use. */
id: `0x${string}`
}
}
Example
const capabilities = await provider.request({
method: 'wallet_sendCalls',
params: [{
capabilities: {
permissions: {
id: '0x...',
},
},
/* ... */
}]
})
Response Capabilities
permissions
Returns the permissions granted on the request.
The following JSON-RPC methods support the permissions
response capability:
type Capability = {
permissions: {
expiry: number,
id: `0x${string}`,
key: {
publicKey: `0x${string}`,
type: 'address' | 'p256' | 'secp256k1' | 'webauthn-p256',
},
permissions: {
calls: {
signature?: string
to?: `0x${string}`
}[],
spend: {
limit: bigint
period: 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year'
token?: `0x${string}`
}[]
}
publicKey: `0x${string}`,
type: 'address' | 'p256' | 'secp256k1' | 'webauthn-p256'
}[]
}
Example
const capabilities = await provider.request({
method: 'wallet_connect',
params: [{
capabilities: {
grantPermissions: { /* ... */ },
},
/* ... */
}]
})
[{ address: '0x1234567890123456789012345678901234567890', capabilities: { permissions: [{ expiry: 1727078400, id: '0x...', key: { publicKey: '0x...', type: 'p256' }, permissions: { calls: [{ signature: 'subscribe()', }], spend: [{ limit: '0x5f5e100', // 100 USDC period: 'day', token: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC }] } }] }, }]
merchant
A merchant server can be set up by the Application to sponsor actions on behalf of their users.
Request Capabilities
merchantRpcUrl
URL of the endpoint that will be used to front (and sponsor) call bundles for users.
The following JSON-RPC methods support the merchantRpcUrl
request capability:
type Capability = {
merchantRpcUrl: string
}
Example
const capabilities = await provider.request({
method: 'wallet_sendCalls',
params: [{
capabilities: {
merchantRpcUrl: 'https://myapp.com/rpc'
},
/* ... */
}]
})
signInWithEthereum
Adds support for ERC-4361 Sign-In with Ethereum.
Request Capabilities
signInWithEthereum
ERC-4361 Sign-In with Ethereum options.
The following JSON-RPC methods support the signInWithEthereum
request capability:
type Capability = {
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
}
}
Example
const capabilities = await provider.request({
method: 'wallet_connect',
params: [{
capabilities: {
signInWithEthereum: {
nonce: await fetch("/api/nonce"),
}
},
/* ... */
}]
})
Response Capabilities
signInWithEthereum
The following JSON-RPC methods support the signInWithEthereum
request capability:
type Capability = {
message: string
signature: `0x${string}`
}
Example
const capabilities = await provider.request({
method: 'wallet_connect',
params: [{
capabilities: {
signInWithEthereum: {
nonce: await fetch("/api/nonce"),
}
},
/* ... */
}]
})