> ## Documentation Index
> Fetch the complete documentation index at: https://docs.socket.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# requestTransaction(): Execute Soroban Contract Calls

> Use requestTransaction() to execute any state-changing Soroban contract call through SocketFi's user-approval and smart wallet authorization workflow.

`requestTransaction()` is the primary method for executing state-changing blockchain operations through SocketFi. When your application calls it, the SDK constructs the transaction, presents an approval screen to the user, routes it through smart wallet authorization and policy enforcement, submits it to Soroban, and returns the result — all without you needing to manage keys, sign transactions, or handle network submission directly.

## Method signature

```ts theme={null}
socketfi.requestTransaction(request: TransactionRequest): Promise<TransactionResult>
```

### TransactionRequest

```ts theme={null}
interface TransactionRequest {
  contractId: string;   // The Soroban contract address to invoke
  method: string;       // The contract method name
  args?: unknown[];     // Arguments to pass to the method (optional)
}
```

| Property     | Type        | Required | Description                                                                      |
| ------------ | ----------- | -------- | -------------------------------------------------------------------------------- |
| `contractId` | `string`    | Yes      | The Soroban contract address (C… Stellar address format)                         |
| `method`     | `string`    | Yes      | The name of the contract method to call                                          |
| `args`       | `unknown[]` | Depends  | Positional arguments for the method. Omit or pass `[]` for zero-argument methods |

### TransactionResult

```ts theme={null}
interface TransactionResult {
  success: boolean;
  transactionHash?: string;  // Present only when success is true
}
```

`transactionHash` is included in the response when `success` is `true`. You can use this hash to display a confirmation link, store it for auditing, or look up the transaction in a Stellar explorer.

## Practical examples

<Accordion title="Transfer tokens">
  Send tokens from the user's wallet to another address.

  ```ts theme={null}
  const result = await socketfi.requestTransaction({
    contractId: tokenContractAddress,
    method: "transfer",
    args: [recipientAddress, amount],
  });

  if (result.success) {
    console.log("Transfer confirmed:", result.transactionHash);
  }
  ```
</Accordion>

<Accordion title="Token approval (allowance)">
  Approve a protocol contract to spend tokens on the user's behalf.

  ```ts theme={null}
  const result = await socketfi.requestTransaction({
    contractId: tokenContractAddress,
    method: "approve",
    args: [spenderAddress, approvalAmount],
  });
  ```
</Accordion>

<Accordion title="Staking">
  Stake tokens in a staking contract.

  ```ts theme={null}
  const result = await socketfi.requestTransaction({
    contractId: stakingContractAddress,
    method: "stake",
    args: [stakeAmount],
  });
  ```
</Accordion>

<Accordion title="Protocol deposit">
  Deposit assets into a lending pool, vault, or other DeFi protocol.

  ```ts theme={null}
  const result = await socketfi.requestTransaction({
    contractId: protocolContractAddress,
    method: "deposit",
    args: [depositAmount],
  });
  ```
</Accordion>

<Accordion title="Claim rewards">
  Claim accumulated rewards from a rewards contract.

  ```ts theme={null}
  const result = await socketfi.requestTransaction({
    contractId: rewardsContractAddress,
    method: "claim",
    args: [],
  });
  ```
</Accordion>

<Accordion title="DAO vote">
  Cast a governance vote on an active proposal.

  ```ts theme={null}
  const result = await socketfi.requestTransaction({
    contractId: daoContractAddress,
    method: "vote",
    args: [proposalId, true], // true = in favor
  });
  ```
</Accordion>

<Accordion title="Mint NFT">
  Mint a new NFT by calling the mint method on a collectible contract.

  ```ts theme={null}
  const result = await socketfi.requestTransaction({
    contractId: nftContractAddress,
    method: "mint",
    args: [metadataUri],
  });
  ```
</Accordion>

## The approval flow

Every call to `requestTransaction()` enters an approval phase before any on-chain action occurs. The SocketFi approval screen shows the user exactly what they're authorizing: the action being performed, which assets are involved, the destination address or protocol, and the estimated fee.

```text theme={null}
requestTransaction() called
         │
         ▼
   Build transaction
         │
         ▼
   Approval screen shown ──► User rejects ──► result.success = false
         │
         ▼ (User approves)
   Smart wallet authorization
         │
         ▼
   Policy enforcement
         │
         ▼
   Network submission
         │
         ▼
   TransactionResult returned
```

Your application's UI should communicate intent in user-facing language, not blockchain mechanics. Prefer "Deposit 100 USDC into Lending Pool" over "Invoke `deposit(100)`" — the approval screen reinforces this context, but your app should set it up clearly beforehand.

## Error handling

Always wrap `requestTransaction()` in a `try/catch` block. The promise rejects on certain failure conditions such as popup blocking or token expiry, and it resolves with `success: false` when the user cancels or a transaction-level failure occurs.

```ts theme={null}
try {
  const result = await socketfi.requestTransaction({
    contractId: tokenContractAddress,
    method: "transfer",
    args: [recipientAddress, amount],
  });

  if (result.success) {
    // Transaction confirmed — safe to update UI
    showSuccess(result.transactionHash);
  } else {
    // User rejected, policy blocked, or contract/network failure
    showError("The transaction could not be completed. Please try again.");
  }
} catch (error) {
  if (error.code === "USER_CANCELLED") {
    // User dismissed the approval screen — no action needed
    resetToIdle();
  } else if (error.code === "POPUP_BLOCKED") {
    showError("Please allow popups for this site and try again.");
  } else if (error.code === "TOKEN_EXPIRED") {
    showError("Your session has expired. Please sign in again.");
  } else {
    showError("An unexpected error occurred.");
    console.error(error);
  }
}
```

<Warning>
  Never update your application's state (balance displays, position data, UI flags) based solely on the fact that `requestTransaction()` was called. Only update state after confirming `result.success === true`. A resolved promise without a truthy `success` field means no on-chain state changed.
</Warning>

## UI state management

A well-designed transaction UI guides the user through each phase of the workflow. The recommended state progression is:

```text theme={null}
idle  ──►  loading  ──►  awaiting_approval  ──►  submitting  ──►  success
                                │
                                ▼
                             rejected  ──►  idle (retry available)
```

Here's a React example that implements this state machine:

```tsx theme={null}
type TxState = "idle" | "loading" | "awaiting_approval" | "submitting" | "success" | "failed";

function TransferButton({ recipient, amount }: Props) {
  const [state, setState] = useState<TxState>("idle");
  const [txHash, setTxHash] = useState<string | null>(null);
  const [errorMsg, setErrorMsg] = useState<string | null>(null);

  const handleTransfer = async () => {
    setState("loading");
    setErrorMsg(null);

    try {
      setState("awaiting_approval");

      const result = await socketfi.requestTransaction({
        contractId: TOKEN_CONTRACT,
        method: "transfer",
        args: [recipient, amount],
      });

      if (result.success) {
        setTxHash(result.transactionHash ?? null);
        setState("success");
      } else {
        setErrorMsg("Transaction was not completed.");
        setState("failed");
      }
    } catch (error) {
      if (error.code === "USER_CANCELLED") {
        setState("idle"); // Silent reset — user chose to cancel
      } else {
        setErrorMsg("An error occurred. Please try again.");
        setState("failed");
      }
    }
  };

  if (state === "success") {
    return <p>Transfer complete! Hash: {txHash}</p>;
  }

  if (state === "failed") {
    return (
      <>
        <p>{errorMsg}</p>
        <button onClick={() => setState("idle")}>Try again</button>
      </>
    );
  }

  return (
    <button onClick={handleTransfer} disabled={state !== "idle"}>
      {state === "awaiting_approval" ? "Waiting for approval…" : "Transfer"}
    </button>
  );
}
```

<Tip>
  When the state is `awaiting_approval`, disable the trigger button and show a spinner or status message. The SocketFi approval popup is open and waiting for user input — triggering a second call at this point will cause unexpected behavior.
</Tip>

## When to use `readContract()` instead

`requestTransaction()` is for state-changing operations only. If you need to query contract state without modifying anything — checking a balance, reading a price, fetching governance data — use `readContract()` instead. Read-only queries don't require user approval and resolve immediately.

```ts theme={null}
// Read-only query — no approval needed, no transaction produced
const balance = await socketfi.readContract({
  contractId: tokenContractAddress,
  method: "balance",
  args: [walletAddress],
});
```
