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

# Earn

## sdk.earn

Earn module for depositing into yield vaults, tracking positions, and withdrawing. For a guided walkthrough, see [Earn](/docs/swift/earn.md).

### getVaults

List the yield vaults available to the environment.

```swift theme={"system"}
try await sdk.earn.getVaults() -> [EarnVaultSummary]
```

#### Returns

* **\[EarnVaultSummary]** — Vaults available to the environment, ordered as the API returns them

#### Example

```swift theme={"system"}
let sdk = DynamicSDK.instance()

let vaults = try await sdk.earn.getVaults()
for vault in vaults {
    print("\(vault.assetSymbol) by \(vault.curator), chain \(vault.chainId)")
}
```

### getVaultDetails

Get full details for one vault, including its contract address and the underlying asset's decimals.

```swift theme={"system"}
try await sdk.earn.getVaultDetails(vaultId: String) -> EarnVaultDetails
```

#### Parameters

* **vaultId** (String) — Opaque vault identifier, from `getVaults`

#### Returns

* **EarnVaultDetails** — Vault metadata including `assetDecimals` and `contractAddress`

#### Example

```swift theme={"system"}
let vault = try await sdk.earn.getVaultDetails(vaultId: vaults[0].vaultId)
print("Asset decimals: \(vault.assetDecimals)")
```

### getVaultPosition

Read a wallet's position in a vault.

```swift theme={"system"}
try await sdk.earn.getVaultPosition(
    vaultId: String,
    ownerAddress: String
) -> EarnVaultPosition
```

#### Parameters

* **vaultId** (String) — Opaque vault identifier
* **ownerAddress** (String) — Wallet address that owns the position

#### Returns

* **EarnVaultPosition** — `shares` and `assets`, both in raw token units. Show `assets`; it grows as yield accrues

#### Example

```swift theme={"system"}
let position = try await sdk.earn.getVaultPosition(
    vaultId: vault.vaultId,
    ownerAddress: wallet.address
)
print("Position: \(position.assets) raw units")
```

### getVaultRewards

Read the rewards a wallet has accrued through a vault.

```swift theme={"system"}
try await sdk.earn.getVaultRewards(
    vaultId: String,
    ownerAddress: String
) -> [EarnVaultReward]
```

#### Parameters

* **vaultId** (String) — Opaque vault identifier
* **ownerAddress** (String) — Wallet address that owns the rewards

#### Returns

* **\[EarnVaultReward]** — Accrued rewards, empty when the wallet has none. Each reward carries `accrued` in raw units and its own `tokenDecimals`

### getVaultPerformance

Read a wallet's Morpho-indexed earnings in one vault.

```swift theme={"system"}
try await sdk.earn.getVaultPerformance(
    vaultId: String,
    ownerAddress: String
) -> EarnVaultPerformance
```

#### Parameters

* **vaultId** (String) — Opaque vault identifier
* **ownerAddress** (String) — Wallet address that owns the position

#### Returns

* **EarnVaultPerformance** — `netEarningsAssets` in raw token units and `returnOnCapital` as a decimal, `nil` when the position has too little history

> [!NOTE]
>
> Indexed values trail the chain head, so `getVaultPosition` remains the live source of truth for the
> position's value. Supports Morpho vaults only; other providers throw an `EarnError` with `statusCode` 400.

### getEarnings

Read a wallet's aggregate earnings across every vault it holds on one EVM chain.

```swift theme={"system"}
try await sdk.earn.getEarnings(
    chainId: Int,
    ownerAddress: String
) -> EarnEarnings
```

#### Parameters

* **chainId** (Int) — EVM chain ID the earnings are aggregated on, for example `8453` for Base
* **ownerAddress** (String) — Wallet address the earnings belong to

#### Returns

* **EarnEarnings** — `totalAssetsUsd` and `totalPnlUsd` totals plus a per-vault `vaults` breakdown. Positions whose provider does not report a cost basis carry `nil` PNL fields

> [!NOTE]
>
> Covers Morpho and Aave positions on EVM chains only. Solana vault positions are not included; use
> `getVaultPosition` for those.

### deposit

Request an unsigned deposit payload.

```swift theme={"system"}
try await sdk.earn.deposit(
    vaultId: String,
    ownerAddress: String,
    amount: String,
    receiverAddress: String? = nil
) -> EarnVaultActionResponse
```

#### Parameters

* **vaultId** (String) — Opaque vault identifier
* **ownerAddress** (String) — Wallet address funding the deposit
* **amount** (String) — Human-readable amount in the vault asset (`"12.5"`), with a leading digit (`"0.01"`, not `".01"`)
* **receiverAddress** (String?, optional) — Wallet that receives the vault shares. Defaults to `ownerAddress`

#### Returns

* **EarnVaultActionResponse** — Carries the `signingPayload` to pass to `execute`

### withdraw

Request an unsigned withdrawal payload.

```swift theme={"system"}
try await sdk.earn.withdraw(
    vaultId: String,
    ownerAddress: String,
    amount: String,
    receiverAddress: String? = nil
) -> EarnVaultActionResponse
```

#### Parameters

* **vaultId** (String) — Opaque vault identifier
* **ownerAddress** (String) — Wallet address that owns the shares
* **amount** (String) — Human-readable amount in the vault asset
* **receiverAddress** (String?, optional) — Wallet that receives the withdrawn assets. Defaults to `ownerAddress`

#### Returns

* **EarnVaultActionResponse** — Carries the `signingPayload` to pass to `execute`

### claim

Request an unsigned payload claiming every reward the wallet has accrued in a vault.

```swift theme={"system"}
try await sdk.earn.claim(
    vaultId: String,
    ownerAddress: String
) -> EarnVaultActionResponse
```

#### Parameters

* **vaultId** (String) — Opaque vault identifier
* **ownerAddress** (String) — Wallet address that owns the rewards

#### Returns

* **EarnVaultActionResponse** — Carries the `signingPayload` to pass to `execute`

> [!NOTE]
>
> Throws an `EarnError` whose `nothingToClaim` is `true` when there is nothing to claim.

### execute

Sign and broadcast a payload returned by `deposit`, `withdraw`, or `claim`.

```swift theme={"system"}
try await sdk.earn.execute(
    payload: EarnSigningPayload,
    wallet: BaseWallet,
    sponsored: Bool? = nil,
    onStepChange: ((EarnExecutionStep) -> Void)? = nil,
    onTransactionStepChange: ((EarnTransactionStepChange) -> Void)? = nil
) -> String
```

#### Parameters

* **payload** (EarnSigningPayload) — The `signingPayload` from a vault action response
* **wallet** (BaseWallet) — Wallet to sign with. Its chain must match the payload's `chainName`
* **sponsored** (Bool?, optional) — How fees are paid. `true` requires gas sponsorship and throws `EarnSponsorError` when unavailable, `false` always pays from the wallet, `nil` sponsors when the environment enables it
* **onStepChange** ((EarnExecutionStep) -> Void, optional) — Reports `.approval` before an ERC-20 approval is sent and `.transaction` before each vault transaction
* **onTransactionStepChange** ((EarnTransactionStepChange) -> Void, optional) — Solana only: reports each transaction's `ordinal`, `total`, and `label` as it begins

#### Returns

* **String** — The vault transaction hash (the last signature on Solana)

#### Example

```swift theme={"system"}
let deposit = try await sdk.earn.deposit(
    vaultId: vault.vaultId,
    ownerAddress: wallet.address,
    amount: "12.5"
)

let transactionHash = try await sdk.earn.execute(
    payload: deposit.signingPayload,
    wallet: wallet,
    onStepChange: { step in
        print("Step: \(step)")
    },
    onTransactionStepChange: { step in
        print("Transaction \(step.ordinal + 1) of \(step.total)")
    }
)
```

An EVM payload sends its ERC-20 approval first when it carries one. A Solana payload signs, sends, and confirms its `transactions` one at a time in `ordinal` order and throws an `EarnSolanaStepError` when a step cannot complete, which may leave earlier transactions already confirmed.

## Error types

### EarnError

Thrown when an Earn API call or execution fails. `statusCode` carries the HTTP status when the failure came from the API, and `nothingToClaim` is `true` for a claim with no claimable rewards (HTTP 422).

### EarnSolanaStepError

Thrown when a transaction in a multi-transaction Solana action cannot complete. Carries `code` (`expired`, `failed`, or `sendFailed`), the stopped transaction's `ordinal`, and the sequence `total`. Transactions before `ordinal` already confirmed on-chain.

### EarnSponsorError

Thrown when `sponsored: true` was required but sponsorship was unavailable or the sponsored transaction failed.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.