> For the complete documentation index, see [llms.txt](https://docs.augustdigital.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.augustdigital.io/developers/typescript-sdk/code-examples/stellar-actions.md).

# Stellar Actions

### Overview

Stellar vault interactions live on the **Stellar adapter** (`sdk.stellar`), not on the higher-level vaults module (which is read-only for Stellar). Unlike EVM — where a deposit is signed and broadcast in one call — Stellar write methods follow a **build → sign → submit** flow:

1. `sdk.stellar.vaultDeposit()` / `sdk.stellar.vaultRedeem()` build an **unsigned transaction** and return it as a base64-encoded **XDR** string.
2. You sign that XDR with the user's Stellar wallet (e.g. [Freighter](https://www.freighter.app/)).
3. `sdk.stellar.submitTransaction()` broadcasts the signed XDR and resolves to the transaction hash once the network confirms it.

The SDK does **not** hardcode vault names like `earnUSDC` or `earnXLM`. You pass a vault's **contract ID** (the `C…` address); resolve it from the vault listing (see [Get Vault Data](#get-vault-data)).

{% hint style="info" %}
`sdk.stellar` runs against Stellar **mainnet**. For testnet, see [Networks](#networks) at the bottom of this page.
{% endhint %}

### Setup

`sdk.stellar` is always available — no extra provider configuration is required, since Stellar vault metadata is served from the August backend.

```typescript
import AugustSDK from '@augustdigital/sdk';

const sdk = new AugustSDK({
  appName: 'your-app-name', // required: stable kebab-case slug identifying your app
});

// Access the Stellar adapter
const stellar = sdk.stellar;
```

{% hint style="info" %}
`AugustSDK` is the package's **default** export — import it as `import AugustSDK from '@augustdigital/sdk'` (not a named import). `appName` is required. No `providers` entry is needed for Stellar, since its vault data is served from the August backend; add `providers` only if you also read EVM/Solana vaults.
{% endhint %}

Signing happens in your app via the user's wallet — there is no `setWalletProvider` step for Stellar. Whatever wallet you use must expose a "sign XDR" call (Freighter's `signTransaction`, for example).

### Adapter API

#### Methods

| Method                                                 | Returns                                 | Description                                   |
| ------------------------------------------------------ | --------------------------------------- | --------------------------------------------- |
| `vaultDeposit({ contractId, amount, senderAddress })`  | `Promise<string>` (XDR)                 | Build an unsigned deposit transaction.        |
| `vaultRedeem({ contractId, shares, receiverAddress })` | `Promise<string>` (XDR)                 | Build an unsigned redeem transaction.         |
| `submitTransaction(signedXdr)`                         | `Promise<string>` (tx hash)             | Submit a signed XDR and poll until confirmed. |
| `getUserPosition(vaultAddress, walletAddress)`         | `Promise<IStellarUserPosition \| null>` | Read the user's on-chain share balance.       |
| `convertToShares(vaultAddress, rawAmount)`             | `Promise<string \| null>`               | Preview shares a deposit amount would yield.  |
| `isStellarAddress(address)`                            | `boolean`                               | Validate a Stellar address (`C…` or `G…`).    |
| `getExplorerLink(id, type?)`                           | `string`                                | Build a Stellar explorer URL.                 |

### Get Vault Data

Stellar vaults appear in the standard listing with `chain_type === 'stellar'`. Use a vault's `address` as the `contractId` for deposit/redeem.

```typescript
// List all vaults, then narrow to Stellar
const vaults = await sdk.getVaults();
const stellarVaults = vaults.filter((v) => v.chain_type === 'stellar');

// e.g. find "earnUSDC" by name/symbol
const earnUsdc = stellarVaults.find((v) => v.name?.includes('earnUSDC'));
const contractId = earnUsdc?.address; // "C…"
```

#### Get User Positions

To include a user's Stellar balances in the unified positions call, pass `stellarWallet` (the user's `G…` address):

```typescript
const positions = await sdk.getVaultPositions({
  stellarWallet: 'G...',
});

positions.forEach((position) => {
  console.log(`Vault: ${position.vault}`);
  console.log(`Balance: ${position.walletBalance.normalized}`);
});
```

For a direct on-chain read of a single vault, use the adapter (this is also how you obtain the `shares` value needed to redeem):

```typescript
const position = await sdk.stellar.getUserPosition(contractId, 'G...');
// { shares: string, decimals: number, decimalsFromFallback?: boolean } | null
```

{% hint style="warning" %}
**Sizing a redeem from `getUserPosition`:** if `position.decimalsFromFallback === true`, the on-chain `decimals()` read failed and `decimals` is a fabricated fallback (`7`). **Do not trust it to size a redeem** — against an offset vault (share decimals = asset + offset) this under-redeems by `10^offset`. Refuse and retry instead.
{% endhint %}

### Vault Deposit

Build an unsigned deposit transaction. This is a **self-deposit**: internally the receiver, from, and operator roles are all set to `senderAddress`.

```typescript
sdk.stellar.vaultDeposit({
  contractId: string;     // Stellar vault contract ("C…")
  amount: string;         // deposit amount in the token's smallest unit
  senderAddress: string;  // user's Stellar account ("G…")
}): Promise<string>       // → unsigned base64 XDR
```

#### Parameters

| Parameter       | Type     | Required | Description                                                                      |
| --------------- | -------- | -------- | -------------------------------------------------------------------------------- |
| `contractId`    | `string` | Yes      | Stellar vault contract address (`C…`).                                           |
| `amount`        | `string` | Yes      | Amount in the deposit token's smallest unit (e.g. 1 USDC @ 7 dp → `"10000000"`). |
| `senderAddress` | `string` | Yes      | User's Stellar account (`G…`); pays for and receives the deposit.                |

#### Example

```typescript
// 1. Build the unsigned transaction
const unsignedXdr = await sdk.stellar.vaultDeposit({
  contractId,
  amount: '10000000', // 1 USDC at 7 decimals
  senderAddress: 'G...',
});

// 2. Sign with the user's wallet (Freighter shown here)
import { signTransaction } from '@stellar/freighter-api';
const { signedTxXdr } = await signTransaction(unsignedXdr, { networkPassphrase: '...' });

// 3. Submit and wait for confirmation
const txHash = await sdk.stellar.submitTransaction(signedTxXdr);
console.log('Deposit confirmed:', txHash);
```

Optionally preview the shares a deposit would mint before building it:

```typescript
const expectedShares = await sdk.stellar.convertToShares(contractId, '10000000');
// string | null
```

### Vault Redeem

Build an unsigned redeem transaction. Redeem burns **shares** (not asset amount), so read the user's position first. This is a **self-redeem**: receiver, owner, and operator roles are all set to `receiverAddress`.

```typescript
sdk.stellar.vaultRedeem({
  contractId: string;       // Stellar vault contract ("C…")
  shares: string;           // amount of shares to redeem, in smallest unit
  receiverAddress: string;  // user's Stellar account ("G…")
}): Promise<string>         // → unsigned base64 XDR
```

#### Parameters

| Parameter         | Type     | Required | Description                                                  |
| ----------------- | -------- | -------- | ------------------------------------------------------------ |
| `contractId`      | `string` | Yes      | Stellar vault contract address (`C…`).                       |
| `shares`          | `string` | Yes      | Shares to redeem, in the share token's smallest unit.        |
| `receiverAddress` | `string` | Yes      | User's Stellar account (`G…`); receives the redeemed assets. |

#### Example

```typescript
// 1. Read the user's share balance
const position = await sdk.stellar.getUserPosition(contractId, 'G...');
if (!position || position.shares === '0') {
  throw new Error('No balance to redeem');
}
if (position.decimalsFromFallback) {
  throw new Error('Decimals unresolved — refusing to size redeem with fallback decimals');
}

// 2. Build the unsigned transaction (redeem all)
const unsignedXdr = await sdk.stellar.vaultRedeem({
  contractId,
  shares: position.shares,
  receiverAddress: 'G...',
});

// 3. Sign with the user's wallet, then submit
const { signedTxXdr } = await signTransaction(unsignedXdr, { networkPassphrase: '...' });
const txHash = await sdk.stellar.submitTransaction(signedTxXdr);
console.log('Redeem confirmed:', txHash);
```

### Submit a Signed Transaction

`submitTransaction` broadcasts a signed XDR and polls until the network confirms it as successful, returning the transaction hash. The XDR must be signed for the same network the adapter is using.

```typescript
const txHash = await sdk.stellar.submitTransaction(signedTxXdr);
```

### Error Handling

`submitTransaction` throws typed [August SDK errors](/developers/typescript-sdk/errors.md):

* **`AugustTimeoutError`** — the transaction was not confirmed within the poll budget.
* **`AugustSDKError`** — the RPC rejected the submission, or the transaction confirmed as failed. Inspect `err.context` for `{ network, status }` and, when the result XDR decodes, a `resultCode` string carrying the transaction-level reason (e.g. `"txBadSeq"`, `"txTooLate"`). `resultCode` is `undefined` when it cannot be decoded.

```typescript
import { AugustSDKError } from '@augustdigital/sdk';

try {
  const txHash = await sdk.stellar.submitTransaction(signedTxXdr);
} catch (err) {
  if (err instanceof AugustSDKError && err.context?.resultCode === 'txBadSeq') {
    // Stale sequence number — rebuild the transaction and resubmit.
  } else {
    throw err;
  }
}
```

### Networks

`sdk.stellar` is hardwired to **mainnet**. To target **testnet**, use the `Stellar` namespace directly with an explicit `network`:

```typescript
import { Stellar } from '@augustdigital/sdk';

// Build an unsigned deposit on testnet
const unsignedXdr = await Stellar.actions.handleStellarDeposit({
  contractId,
  amount: '10000000',
  senderAddress: 'G...',
  network: 'testnet',
});

// Submit on testnet
const txHash = await Stellar.submit.submitStellarTransaction(signedTxXdr, 'testnet');
```

### Notes & Caveats

* **Self-deposit / self-redeem only.** All role addresses are set to the single account you pass; there is no third-party/operator variant.
* **Standard vault ABI assumed.** Redeem assumes the deployed vault exposes `redeem(shares, receiver, owner, operator)`. A divergent ABI surfaces as a generic Soroban simulation error.
* **Read-only on the vaults module.** Available redemptions and redemption history are **not yet supported** for Stellar vaults; deposit/redeem are available only on `sdk.stellar`.
