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

# StewardClient

> Complete reference for the StewardClient TypeScript SDK.

# StewardClient

The `StewardClient` class provides typed methods for all Steward API operations.

## Constructor

```typescript theme={null}
import { StewardClient } from "@stwd/sdk";

const client = new StewardClient({
  baseUrl: string;        // Steward API URL (e.g., "https://api.steward.fi")
  apiKey?: string;        // Tenant API key (X-Steward-Key header)
  bearerToken?: string;   // Agent JWT (Authorization: Bearer header)
  tenantId?: string;      // Optional tenant ID header
});
```

<Note>
  When both `apiKey` and `bearerToken` are provided, `bearerToken` takes priority. Use `apiKey` for tenant operations and `bearerToken` for agent operations.
</Note>

## Agent Methods

### createWallet

Creates a new agent with encrypted EVM and Solana wallets.

```typescript theme={null}
const agent = await client.createWallet(
  agentId: string,
  name: string,
  platformId?: string
): Promise<AgentIdentity>;
```

```typescript theme={null}
const agent = await client.createWallet("my-agent", "My Agent");
// Returns: { id, name, tenantId, walletAddresses: { evm, solana }, createdAt }
```

### listAgents

Lists all agents for the authenticated tenant.

```typescript theme={null}
const agents = await client.listAgents(): Promise<AgentIdentity[]>;
```

### getAgent

Gets a single agent by ID.

```typescript theme={null}
const agent = await client.getAgent(agentId: string): Promise<AgentIdentity>;
```

### createWalletBatch

Creates multiple agents in one request with optional shared policies.

```typescript theme={null}
const result = await client.createWalletBatch(
  agents: BatchAgentSpec[],
  policies?: PolicyRule[]
): Promise<BatchCreateResult>;
```

```typescript theme={null}
const result = await client.createWalletBatch(
  [
    { id: "agent-1", name: "Agent One" },
    { id: "agent-2", name: "Agent Two" },
  ],
  [{ id: "limit", type: "spending-limit", enabled: true, config: { maxPerDay: "1000000000000000000" } }]
);
// Returns: { created: AgentIdentity[], errors: { id, error }[] }
```

## Signing Methods

### signTransaction

Signs and optionally broadcasts an EVM transaction.

```typescript theme={null}
const result = await client.signTransaction(
  agentId: string,
  tx: SignTransactionInput
): Promise<SignTransactionResult>;
```

```typescript theme={null}
interface SignTransactionInput {
  to: string;          // Destination address
  value: string;       // Wei amount
  data?: string;       // Calldata
  chainId?: number;    // Chain ID (default: server's active chain)
  broadcast?: boolean; // Broadcast after signing (default: true)
}

// Result is one of:
type SignTransactionResult =
  | { txHash: string }              // Broadcast success
  | { signedTx: string }            // Sign-only (broadcast: false)
  | { status: "pending_approval"; results: PolicyResult[] }; // Queued
```

```typescript theme={null}
const result = await client.signTransaction("my-agent", {
  to: "0xDEX_ROUTER",
  value: "50000000000000000",
  chainId: 8453,
});

if ("txHash" in result) {
  console.log("TX hash:", result.txHash);
} else if ("signedTx" in result) {
  console.log("Signed TX:", result.signedTx);
} else {
  console.log("Needs approval:", result.results);
}
```

### signTypedData

Signs EIP-712 structured data.

```typescript theme={null}
const result = await client.signTypedData(
  agentId: string,
  input: SignTypedDataInput
): Promise<{ signature: string }>;
```

### signSolanaTransaction

Signs a serialized Solana transaction.

```typescript theme={null}
const result = await client.signSolanaTransaction(
  agentId: string,
  input: SignSolanaTransactionInput
): Promise<SignSolanaTransactionResult>;
```

```typescript theme={null}
interface SignSolanaTransactionInput {
  transaction: string; // Base64-encoded serialized transaction
  chainId?: number;    // 101 = mainnet, 102 = devnet
  broadcast?: boolean;
}
```

### signBitcoinPsbt

Signs a scoped Bitcoin PSBT for an agent wallet. Steward returns a signed PSBT
and a Steward `transactionId`; it does not broadcast.

```typescript theme={null}
const result = await client.signBitcoinPsbt(
  agentId: string,
  input: SignBitcoinPsbtInput
): Promise<SignBitcoinPsbtResult>;
```

```typescript theme={null}
interface SignBitcoinPsbtInput {
  walletScope: string;  // e.g. "bitcoin:testnet:p2wpkh:0:0:0"
  psbtBase64: string;   // Base64-encoded PSBT
  finalize?: boolean;   // Return raw tx metadata when fully finalizable
  referenceId?: string; // Caller-stable tracking ID for audit/history lookup
}

interface SignBitcoinPsbtResult {
  transactionId: string; // Steward transaction record ID
  signedPsbtBase64: string;
  signedInputs: number;
  walletScope: string;
  walletAddress: string;
  addressType: "p2wpkh" | "p2tr";
  network: "mainnet" | "testnet";
  finalizedTxHex?: string;
  txId?: string;
  vsize?: number;
  feeSats?: string;
}
```

```typescript theme={null}
const referenceId = "withdrawal-123";

const result = await client.signBitcoinPsbt("my-agent", {
  walletScope: "bitcoin:testnet:p2wpkh:0:0:0",
  psbtBase64,
  finalize: true,
  referenceId,
});

console.log(result.transactionId);

if (result.finalizedTxHex) {
  // Steward does not broadcast. Before retrying a downstream broadcast, check
  // result.txId with your broadcaster or indexer.
}
```

Steward decodes standard PSBT destination outputs and enforces fee caps,
spend/address policies, and Bitcoin raw-signing-chain policy requirements before
signing. For safe retries, reuse a stable `referenceId` and, where accepted by
your deployment, the same `Idempotency-Key` header. If `finalize: true` returns
`finalizedTxHex`, avoid blindly retrying broadcast attempts; first check whether
the returned Bitcoin `txId` is already known to your broadcaster or indexer.

### signMessage

Signs an arbitrary message.

```typescript theme={null}
const result = await client.signMessage(
  agentId: string,
  message: string
): Promise<{ signature: string }>;
```

## Encrypted Key Import Methods

Agent-vault import helpers require a tenant owner/admin bearer session with
recent MFA. User-wallet import helpers require the authenticated user's bearer
session with recent MFA. Both flows use a server X25519 init response and then
submit only an encrypted envelope; do not include a plaintext `privateKey`
field.

```typescript theme={null}
const agentSession = await client.initializeEncryptedAgentKeyImport(
  "my-agent",
  "evm"
);

await client.submitEncryptedAgentKeyImport("my-agent", {
  importSessionId: agentSession.importSessionId,
  ephemeralPublicKey,
  iv,
  ciphertext,
  tag,
});
```

```typescript theme={null}
const userSession = await client.initializeEncryptedUserWalletKeyImport(
  "evm",
  { walletIndex: 2 }
);

await client.submitEncryptedUserWalletKeyImport({
  importSessionId: userSession.importSessionId,
  ephemeralPublicKey,
  iv,
  ciphertext,
  tag,
  walletIndex: userSession.aad.walletIndex,
});
```

Init sessions are bound to tenant/app/user/agent/wallet fields returned in
`aad`. Wrong-agent and wrong-wallet-index submits fail without consuming the
original session; validated submits consume the session atomically, so replay
fails.

## Query Methods

### getBalance

Gets the native token balance for an agent's wallet.

```typescript theme={null}
const balance = await client.getBalance(
  agentId: string,
  chainId?: number
): Promise<AgentBalance>;
```

### getAddresses

Gets all wallet addresses across chain families.

```typescript theme={null}
const addresses = await client.getAddresses(
  agentId: string
): Promise<GetAddressesResult>;
```

### getHistory

Gets the transaction history for an agent.

```typescript theme={null}
const history = await client.getHistory(
  agentId: string
): Promise<StewardHistoryEntry[]>;
```

### rpcPassthrough

Proxies a read-only RPC call.

```typescript theme={null}
const result = await client.rpcPassthrough(
  agentId: string,
  input: { method: string; params?: unknown[]; chainId: number }
): Promise<RpcResponse>;
```

## Global Wallet Methods

Global wallet helpers require a user bearer token. Pass `walletIndex` when the
user selected a non-default embedded wallet; the server binds consent, scan,
confirmation, audit, and execution to that same wallet index plus wallet agent
id/address. Omitting `walletIndex` selects index `0`.

```typescript theme={null}
await client.approveGlobalWalletConsent({
  appId: "tenant/client",
  origin: "https://app.example",
  scopes: ["eth_accounts", "eth_sendTransaction"],
  walletIndex: 2,
});

const scan = await client.scanGlobalWalletTransaction({
  appId: "tenant/client",
  origin: "https://app.example",
  walletIndex: 2,
  params: [{ from, to, value: "0x1", chainId: "0x2105" }],
});

const confirmation = await client.confirmGlobalWalletAction({
  appId: "tenant/client",
  origin: "https://app.example",
  method: "eth_sendTransaction",
  walletIndex: 2,
  params: [{ from, to, value: "0x1", chainId: "0x2105" }],
});

await client.globalWalletRpc({
  appId: "tenant/client",
  origin: "https://app.example",
  method: "eth_sendTransaction",
  walletIndex: 2,
  confirmationId: confirmation.confirmationId,
  params: [{ from, to, value: "0x1", chainId: "0x2105" }],
});
```

Contract calldata remains blocked for global wallet transaction execution until
selector-aware scanning and policy checks are configured for that deployment.

## App Client Methods

Tenant app-client helpers expose the same `TenantAppClient` shape documented in
the control-plane API. Native app clients can set iOS and Android allowlists
with `allowedBundleIds` and `allowedPackageNames`; device-code auth then checks
`X-Steward-Native-Bundle-Id`, `X-Steward-Native-Package-Name`, or matching JSON
fields against the enabled client.

```typescript theme={null}
await client.createTenantAppClient("tenant-1", {
  id: "ios-prod",
  name: "iOS Production",
  environment: "production",
  enabled: true,
  allowedBundleIds: ["com.example.app"],
  allowedRedirectUrls: ["com.example.app://auth/callback"],
});

const clients = await client.listTenantAppClients("tenant-1");
```

## Tenant User Methods

### bulkRemediateTenantWalletPolicyViolations

Removes selected EVM/Solana linked wallet accounts from tenant members after an
owner/admin has reviewed a one-third-party-wallet policy violation report.
Requires a user bearer token scoped to the tenant with recent MFA.

```typescript theme={null}
const result = await client.bulkRemediateTenantWalletPolicyViolations(
  tenantId: string,
  wallets: Array<{ userId: string; accountId: string }>
): Promise<TenantWalletPolicyBulkRemediationResponse>;
```

The API caps requests at 50 items and returns per-item success/error results so
callers can retry failed selections without repeating successful remediations.

## Policy Methods

### getPolicies

Gets all policies for an agent.

```typescript theme={null}
const policies = await client.getPolicies(
  agentId: string
): Promise<PolicyRule[]>;
```

### setPolicies

Replaces all policies for an agent.

```typescript theme={null}
await client.setPolicies(
  agentId: string,
  policies: PolicyRule[]
): Promise<void>;
```

## Additional API Areas

This page covers the core `StewardClient` methods. The archived root SDK reference also covered webhook, tenant configuration, dashboard, and approval APIs; those surfaces now live in the API reference:

* [Approvals](/api-reference/approvals)
* [Webhooks](/api-reference/webhooks)
* [Tenant Config](/api-reference/tenant-config)
* [Dashboard](/api-reference/dashboard)

## Error Handling

All methods throw `StewardApiError` on failure:

```typescript theme={null}
import { StewardApiError } from "@stwd/sdk";

try {
  await client.signTransaction("my-agent", { ... });
} catch (error) {
  if (error instanceof StewardApiError) {
    console.error(`HTTP ${error.status}: ${error.message}`);
    
    // For signing errors, data may contain policy results
    if (error.data?.results) {
      console.error("Policy results:", error.data.results);
    }
  }
}
```

```typescript theme={null}
class StewardApiError<TData = unknown> extends Error {
  readonly status: number;  // HTTP status code (0 for network errors)
  readonly data?: TData;    // Response data (may include policy results)
}
```
