SDK
grantSession
Grant a scoped session key for a wallet. The admin signer authorizes the session onchain; from that point forward the session can act on the wallet within its permissions, enforced onchain.
import { createClient, BNB_TESTNET, signerFromPrivateKey } from "@functornetwork/agentic-wallet";
const client = createClient({ chains: [BNB_TESTNET] });
const admin = signerFromPrivateKey("0x...");
const wallet = await client.createWallet({ signer: admin });
const session = await client.grantSession({
wallet,
signer: admin,
permissions: {
calls: [{ to: "0xUniswapRouter..." }],
spend: [{
limit: 100_000_000n, // 100 USDC (6 decimals)
period: "day",
token: "0xUSDC...",
}],
},
expiry: Math.floor(Date.now() / 1000) + 7 * 24 * 60 * 60, // 7 days
});
// Hand `session` to whichever process runs the agent.Keystore impact
The session's public key is written to Keystore via the Controller. From that moment, any tool reading getActiveKeys on the wallet sees this session. Reads are free and unlimited.
Parameters
client.grantSession(opts: ClientGrantSessionOptions): Promise<Session>;
type ClientGrantSessionOptions = {
wallet: Wallet;
signer: Signer; // the wallet's admin signer
permissions: SessionPermissions;
/** Unix epoch seconds. Most apps use Date.now()/1000 + N. */
expiry: number;
/** Bring your own session signer, or omit to let the SDK generate one. */
sessionSigner?: Signer;
/** Fee token (default: native token). */
feeToken?: Address;
/** Target chain. Defaults to the client's default chain. */
chainId?: number;
};See Sessions for the full permission shape reference.
Returns
type Session = {
walletAddress: Address;
signer: Signer; // session key. Agent signs with this.
publicKey: Hex;
permissions: SessionPermissions;
expiry: number;
};What lands onchain
In a single userOp:
- The session's public key is registered in Keystore, making it discoverable by any tool.
- The session is authorized on the wallet's smart account with its permissions hash.
Both happen atomically. There is no intermediate state where one exists without the other.
Notes
- Persist the full
Sessionobject, not justpublicKey. The agent needspermissions + expirybyte-exact at execute time. - If you generated the session signer (omitted
sessionSigner), persistsession.signersecurely. Losing it means the session can no longer sign. permissions.callsomitted = unrestricted. Always set bothcallsandspendunless you specifically want an open-scope session.