Skip to main content
This hook uses the session key signature (4-element format) instead of the owner signature. The session must be registered on-chain first via useAddSessionKeyToContract.

Usage

const { 
  executeWithSession,
  executeWithSessionAsync, 
  data, 
  isLoading, 
  error,
  isSuccess,
  reset
} = useExecuteWithSession();

Parameters

ParameterTypeRequiredDescription
params.encryptKeystringYesPIN to decrypt the session private key
params.walletWalletDataYesWallet object (session executes on behalf of this wallet)
params.sessionSessionKeyDataYesSession key data from useCreateSessionKey
params.callsCall[]YesArray of contract calls to execute
bearerTokenstringYesAuthentication token from your auth provider

Call Structure

{
  contractAddress: string;  // Target contract address
  entrypoint: string;       // Function name to call
  calldata: string[];       // Function arguments
}

Return Value

PropertyTypeDescription
executeWithSessionfunctionTrigger execution (fire-and-forget)
executeWithSessionAsyncfunctionTrigger execution (returns Promise with tx hash)
datastringTransaction hash
isLoadingbooleanWhether execution is in progress
isErrorbooleanWhether an error occurred
errorError | nullError details if any
isSuccessbooleanWhether execution succeeded
resetfunctionReset mutation state

Example: Token Transfer

import { useExecuteWithSession } from "@chipi-stack/chipi-react";

const USDC_ADDRESS = "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8";

export function SessionTransfer() {
  const { executeWithSessionAsync, isLoading, error, data: txHash } = useExecuteWithSession();
  const [amount, setAmount] = useState('');
  const [recipient, setRecipient] = useState('');

  const handleTransfer = async () => {
    const bearerToken = await getBearerToken();
    const session = JSON.parse(localStorage.getItem('chipiSession')!);
    const pin = await promptForPin(); // Your PIN input method

    try {
      const hash = await executeWithSessionAsync({
        params: {
          encryptKey: pin,
          wallet: {
            publicKey: wallet.publicKey,
            encryptedPrivateKey: wallet.encryptedPrivateKey,
            walletType: "CHIPI",
          },
          session,
          calls: [{
            contractAddress: USDC_ADDRESS,
            entrypoint: "transfer",
            calldata: [recipient, amount, "0x0"],
          }],
        },
        bearerToken,
      });
      
      console.log('Transfer executed:', hash);
    } catch (err) {
      console.error('Transfer failed:', err);
    }
  };

  return (
    <div className="p-6 bg-white rounded-lg shadow">
      <h2 className="text-xl font-semibold mb-4">Transfer with Session</h2>
      
      <div className="space-y-4">
        <input
          value={recipient}
          onChange={(e) => setRecipient(e.target.value)}
          placeholder="Recipient address (0x...)"
          className="w-full p-2 border rounded"
        />
        
        <input
          value={amount}
          onChange={(e) => setAmount(e.target.value)}
          placeholder="Amount (in smallest units)"
          className="w-full p-2 border rounded"
        />
        
        <button
          onClick={handleTransfer}
          disabled={isLoading}
          className="w-full bg-green-600 text-white py-2 rounded hover:bg-green-700 disabled:bg-gray-400"
        >
          {isLoading ? 'Executing...' : 'Transfer'}
        </button>
      </div>

      {error && (
        <div className="mt-4 p-3 bg-red-50 text-red-700 rounded">
          Error: {error.message}
        </div>
      )}

      {txHash && (
        <div className="mt-4 p-3 bg-green-50 rounded">
          <a 
            href={`https://starkscan.co/tx/${txHash}`}
            target="_blank"
            rel="noopener noreferrer"
            className="text-green-700 hover:underline"
          >
            View transaction
          </a>
        </div>
      )}
    </div>
  );
}

Example: Gaming Actions

import { useExecuteWithSession } from "@chipi-stack/chipi-react";

const GAME_CONTRACT = "0x...";

export function GameBoard() {
  const { executeWithSessionAsync, isLoading } = useExecuteWithSession();

  const makeMove = async (moveData: string) => {
    const session = JSON.parse(localStorage.getItem('chipiSession')!);
    const bearerToken = await getBearerToken();

    // Execute instantly - no wallet popup!
    await executeWithSessionAsync({
      params: {
        encryptKey: userPin,
        wallet: { ...wallet, walletType: "CHIPI" },
        session,
        calls: [{
          contractAddress: GAME_CONTRACT,
          entrypoint: "make_move",
          calldata: [moveData],
        }],
      },
      bearerToken,
    });
  };

  return (
    <div className="grid grid-cols-3 gap-2">
      {[1, 2, 3, 4, 5, 6, 7, 8, 9].map((cell) => (
        <button
          key={cell}
          onClick={() => makeMove(cell.toString())}
          disabled={isLoading}
          className="h-20 bg-blue-500 text-white rounded hover:bg-blue-600 disabled:bg-gray-400"
        >
          {cell}
        </button>
      ))}
    </div>
  );
}

Multi-Call Transactions

Execute multiple calls in a single transaction:
const txHash = await executeWithSessionAsync({
  params: {
    encryptKey: pin,
    wallet: walletData,
    session,
    calls: [
      // Approve spending
      {
        contractAddress: USDC_ADDRESS,
        entrypoint: "approve",
        calldata: [SWAP_CONTRACT, amount, "0x0"],
      },
      // Execute swap
      {
        contractAddress: SWAP_CONTRACT,
        entrypoint: "swap",
        calldata: [USDC_ADDRESS, ETH_ADDRESS, amount, minReceived],
      },
    ],
  },
  bearerToken,
});

Error Handling

ErrorCauseSolution
Session execution only supports CHIPI walletsWallet is ARGENT typeUse a CHIPI wallet
Session has expiredvalidUntil timestamp passedCreate and register a new session
Session not foundNot registered on-chainCall useAddSessionKeyToContract first
Max calls exceededremainingCalls is 0Create a new session with higher maxCalls
Entrypoint not allowedFunction not in whitelistRegister session with correct allowedEntrypoints
Session transactions decrement remainingCalls on the contract. Monitor usage with useGetSessionData and create new sessions before exhaustion.
For the best UX, pre-create sessions during onboarding and store the PIN securely. This allows instant transactions without prompting for PIN each time.