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

# Loopscale Instructions

> Run lender-side and borrower-side Loopscale flows through policy-gated Strategy Vault execution

The Loopscale instructions module enables vault managers and allocators to interact with [Loopscale](https://docs.loopscale.com/introduction/overview) through `LoopscaleClient`. Unlike the other integrations that start from `createVaultSyncTransaction` directly, Loopscale flows start from raw [Loopscale API](https://docs.loopscale.com/api-reference/introduction/introduction) responses and then turn those responses into executable vault transactions.

Loopscale exposes two distinct Strategy Vault surfaces:

* **Lender-side strategy flows** — create, fund, update, withdraw from, and close a [Loopscale strategy](https://docs.loopscale.com/protocol-concepts/loans-and-orders)
* **Borrower-side loan flows** — create a loan, deposit collateral, borrow principal, repay, withdraw collateral, and close the loan

## How co-signing works

Loopscale transaction flow is slightly different from the other Strategy Vault integrations:

1. Loopscale constructs the transaction flow through its API.
2. The SDK turns that raw response into manager-facing vault transactions and signs them locally.
3. If a transaction is flagged with `requiresLoopscaleCoSign`, send that transaction to `client.coSign(...)`.
4. Submit the returned co-signed transaction on-chain.

Only the wrapped Loopscale transaction belongs to Loopscale's signing domain. Setup transactions and other local top-level transactions should be sent directly.

<Note>
  If you need more detail on Loopscale-specific mechanics, markets, or transaction endpoints, visit the [Loopscale Docs](https://docs.loopscale.com/).
</Note>

## Loopscale client

Create a client once and reuse it across your strategy or loan flow:

```typescript theme={null}
import { LoopscaleClient } from "@exponent-labs/exponent-sdk";

const client = new LoopscaleClient({
  connection,
  userWallet: vault.state.squadsVault,
});
```

## Choose an execution path

Loopscale transaction methods return raw Loopscale responses. After each call, choose one of two execution paths.

### Prepare appendable transactions

Use `prepareVaultTransactions(...)` when you want lower-level transaction pieces that you can compose yourself.

```typescript theme={null}
import { SQUADS_PROGRAM_ID } from "@exponent-labs/exponent-sdk";

const preparedTransactions = await client.prepareVaultTransactions({
  response,
  context: {
    connection,
    signer: wallet.publicKey,
    vaultPda: vault.state.squadsVault,
    vaultAddress: vault.selfAddress,
    squadsProgram: SQUADS_PROGRAM_ID,
  },
});
```

Each prepared entry contains:

* `setupInstructions` — send these first when present
* `instructions` — the main instruction list for the step
* `signers` — any extra local signers required for the step
* `addressLookupTableAddresses` — lookup tables needed to compile the transaction
* `requiresLoopscaleCoSign` — whether the main transaction still needs `client.coSign(...)`

### Build ready-to-send transactions

Use `buildVaultTransactions(...)` when you want locally signed `VersionedTransaction`s that are ready to send.

```typescript theme={null}
import {
  LoopscaleClient,
  SQUADS_PROGRAM_ID,
  type LoopscaleTransactionResponse,
} from "@exponent-labs/exponent-sdk";

async function executeLoopscaleResponse(response: LoopscaleTransactionResponse) {
  const builtTransactions = await client.buildVaultTransactions({
    response,
    context: {
      connection,
      signer: wallet.publicKey,
      signers: [wallet],
      vaultPda: vault.state.squadsVault,
      vaultAddress: vault.selfAddress,
      squadsProgram: SQUADS_PROGRAM_ID,
    },
  });

  for (const builtTransaction of builtTransactions) {
    const transaction = builtTransaction.requiresLoopscaleCoSign
      ? await client.coSign(builtTransaction.transaction)
      : builtTransaction.transaction;

    await connection.sendTransaction(transaction, { skipPreflight: false });
  }
}
```

`requiresLoopscaleCoSign` is the exact boundary for Loopscale MPC signing. Only call `coSign(...)` for transactions flagged `true`.

<Note>
  `buildVaultTransactions(...)` requires `context.signers[0]` to match `context.signer`.
</Note>

<Note>
  If you are already using [VaultTransactionBuilder](/developer-strategy-vaults/vault-transaction-builder), pass the raw response to `addLoopscaleResponse(...)` and let `result.send()` handle any required Loopscale co-signing.
</Note>

***

## Create strategy

`createStrategy(...)` returns a raw Loopscale batch response. The response itself is enough to execute the create flow. If you want to keep the created strategy address for later calls, you can extract it from the response.

```typescript theme={null}
const response = await client.createStrategy({
  principalMint: new PublicKey("..."),
  lender: vault.state.squadsVault,
  amount: 0,
});

await executeLoopscaleResponse(response);

const strategyAddress = await client.extractCreatedStrategyAddress(response);
```

### Parameters

| Parameter                 | Type                         | Description                                  |
| ------------------------- | ---------------------------- | -------------------------------------------- |
| `principalMint`           | `PublicKey \| string`        | Mint of the strategy principal asset         |
| `lender`                  | `PublicKey \| string`        | Vault-owned lender address                   |
| `amount`                  | `bigint \| number`           | Initial funding amount                       |
| `collateralTerms`         | `Array<...>`                 | Optional collateral and APY configuration    |
| `marketInformation`       | `PublicKey \| string`        | Optional external market information account |
| `externalYieldSourceArgs` | `TxnExternalYieldSourceArgs` | Optional external yield source configuration |

A matching policy must exist before executing. See [Policy Builders](/developer-strategy-vaults/policy-builders#loopscale-policy). See also [Loopscale: Create Strategy](https://docs.loopscale.com/api-reference/transactions/strategy/create-strategy) for API details.

***

## Deposit strategy

```typescript theme={null}
const response = await client.depositStrategy({
  strategy: strategyAddress,
  amount: 500_000_000,
});

await executeLoopscaleResponse(response);
```

### Parameters

| Parameter  | Type                  | Description                    |
| ---------- | --------------------- | ------------------------------ |
| `strategy` | `PublicKey \| string` | Loopscale strategy account     |
| `amount`   | `bigint \| number`    | Amount of principal to deposit |

A matching policy must exist before executing. See [Policy Builders](/developer-strategy-vaults/policy-builders#loopscale-policy). See also [Loopscale: Deposit Strategy](https://docs.loopscale.com/api-reference/transactions/strategy/deposit-strategy) for API details.

***

## Update strategy

```typescript theme={null}
const response = await client.updateStrategy({
  strategy: strategyAddress,
  updateParams: {
    originationsEnabled: true,
    liquidityBuffer: 500,
  },
});

await executeLoopscaleResponse(response);
```

`updateStrategy(...)` also accepts `collateralTerms` when you need to change collateral matrices or duration / APY settings.

### Parameters

| Parameter         | Type                        | Description                        |
| ----------------- | --------------------------- | ---------------------------------- |
| `strategy`        | `PublicKey \| string`       | Loopscale strategy account         |
| `collateralTerms` | `StrategyCollateralUpdates` | Optional collateral matrix updates |
| `updateParams`    | `EditStrategySettingsArgs`  | Optional strategy settings updates |

A matching policy must exist before executing. See [Policy Builders](/developer-strategy-vaults/policy-builders#loopscale-policy). See also [Loopscale: Update Strategy](https://docs.loopscale.com/api-reference/transactions/strategy/update-strategy) for API details.

***

## Withdraw strategy

```typescript theme={null}
const response = await client.withdrawStrategy({
  strategy: strategyAddress,
  amount: 0,
  withdrawAll: true,
});

await executeLoopscaleResponse(response);
```

### Parameters

| Parameter     | Type                  | Description                           |
| ------------- | --------------------- | ------------------------------------- |
| `strategy`    | `PublicKey \| string` | Loopscale strategy account            |
| `amount`      | `bigint \| number`    | Amount of principal to withdraw       |
| `withdrawAll` | `boolean`             | Whether to withdraw the full position |

A matching policy must exist before executing. See [Policy Builders](/developer-strategy-vaults/policy-builders#loopscale-policy). See also [Loopscale: Withdraw Strategy](https://docs.loopscale.com/api-reference/transactions/strategy/withdraw-strategy) for API details.

***

## Close strategy

```typescript theme={null}
const response = await client.closeStrategy({
  strategy: strategyAddress,
});

await executeLoopscaleResponse(response);
```

### Parameters

| Parameter  | Type                  | Description                |
| ---------- | --------------------- | -------------------------- |
| `strategy` | `PublicKey \| string` | Loopscale strategy account |

A matching policy must exist before executing. See [Policy Builders](/developer-strategy-vaults/policy-builders#loopscale-policy). See also [Loopscale: Close Strategy](https://docs.loopscale.com/api-reference/transactions/strategy/close-strategy) for API details.

***

## Create loan

`createLoan(...)` returns a raw Loopscale response plus a `loanAddress` string you can use immediately in follow-up calls.

```typescript theme={null}
const response = await client.createLoan({
  borrower: vault.state.squadsVault,
  depositCollateral: [{
    collateralAmount: 500_000_000,
    collateralAssetData: {
      Spl: { mint: new PublicKey("...").toBase58() },
    },
  }],
  principalRequested: [{
    ledgerIndex: 0,
    principalAmount: 100_000_000,
    principalMint: new PublicKey("..."),
    strategy: strategyAddress,
    durationIndex: 0,
    expectedLoanValues: {
      expectedApy: 0,
      expectedLqt: [0, 0, 0, 0, 0],
    },
  }],
});

const loanAddress = new PublicKey(response.loanAddress);

await executeLoopscaleResponse(response);
```

### Parameters

| Parameter            | Type                  | Description                                               |
| -------------------- | --------------------- | --------------------------------------------------------- |
| `borrower`           | `PublicKey \| string` | Vault-owned borrower address                              |
| `depositCollateral`  | `Array<...>`          | Collateral legs to deposit into the loan                  |
| `principalRequested` | `Array<...>`          | Requested principal legs tied to strategies and durations |
| `assetIndexGuidance` | `number[]`            | Optional asset index hints                                |
| `loanNonce`          | `string`              | Optional loan nonce override                              |
| `isLoop`             | `boolean`             | Optional loop-mode flag                                   |

A matching policy must exist before executing. See [Policy Builders](/developer-strategy-vaults/policy-builders#loopscale-policy). See also [Loopscale: Create Loan](https://docs.loopscale.com/api-reference/transactions/borrow/create-loan) for API details.

***

## Deposit collateral

```typescript theme={null}
const response = await client.depositCollateral({
  loan: loanAddress,
  depositMint: new PublicKey("..."),
  amount: 500_000_000,
  assetType: 0,
  assetIdentifier: new PublicKey("..."),
  expectedLoanValues: {
    expectedApy: 0,
    expectedLqt: [0, 0, 0, 0, 0],
  },
});

await executeLoopscaleResponse(response);
```

### Parameters

| Parameter            | Type                                               | Description                             |
| -------------------- | -------------------------------------------------- | --------------------------------------- |
| `loan`               | `PublicKey \| string`                              | Loopscale loan account                  |
| `depositMint`        | `PublicKey \| string`                              | Mint being deposited as collateral      |
| `amount`             | `bigint \| number`                                 | Collateral amount                       |
| `assetType`          | `number`                                           | Loopscale asset type discriminator      |
| `assetIdentifier`    | `PublicKey \| string`                              | Asset identifier for the collateral leg |
| `assetIndexGuidance` | `number[]`                                         | Optional asset index hints              |
| `expectedLoanValues` | `{ expectedApy?: number; expectedLqt?: number[] }` | Optional loan-state hints               |

A matching policy must exist before executing. See [Policy Builders](/developer-strategy-vaults/policy-builders#loopscale-policy). See also [Loopscale: Deposit Collateral](https://docs.loopscale.com/api-reference/transactions/borrow/deposit-collateral) for API details.

***

## Borrow principal

Before you request a borrow, inspect the available Loopscale lending options for the principal, collateral, and duration you want to use. In the SDK, the usual discovery calls are:

* `getQuotes(...)` when you want a list of current lend orders for a principal / collateral / duration combination
* `getMaxQuote(...)` when you already know the collateral input and want the top matching quote for that borrow

After you choose the strategy you want to borrow from, pass that strategy address into `borrowPrincipal(...)`.

```typescript theme={null}
const response = await client.borrowPrincipal({
  loan: loanAddress,
  strategy: strategyAddress,
  borrowParams: {
    amount: 100_000_000,
    durationIndex: 0,
    expectedLoanValues: {
      expectedApy: 0,
      expectedLqt: [0, 0, 0, 0, 0],
    },
  },
});

await executeLoopscaleResponse(response);
```

### Parameters

| Parameter         | Type                                             | Description                               |
| ----------------- | ------------------------------------------------ | ----------------------------------------- |
| `loan`            | `PublicKey \| string`                            | Loopscale loan account                    |
| `strategy`        | `PublicKey \| string`                            | Strategy providing the borrowed principal |
| `borrowParams`    | `{ amount, durationIndex, expectedLoanValues? }` | Requested borrow amount and duration      |
| `refinanceParams` | `{ ledgerIndex, durationIndex }`                 | Optional refinance target                 |
| `isLoop`          | `boolean`                                        | Optional loop-mode flag                   |

A matching policy must exist before executing. See [Policy Builders](/developer-strategy-vaults/policy-builders#loopscale-policy). See also [Loopscale: Borrow Principal](https://docs.loopscale.com/api-reference/transactions/borrow/borrow-principal) for API details.

<Note>
  If you need more detail on Loopscale-specific market discovery and borrow selection, visit the [Loopscale Docs](https://docs.loopscale.com/). The official data endpoints are [Get quotes](https://docs.loopscale.com/api-reference/data/markets/get-quotes) and [Get best quote](https://docs.loopscale.com/api-reference/data/markets/get-best-quote).
</Note>

***

## Repay loan

`repayLoanSimple(...)` builds the raw `repay_simple` Loopscale response.

```typescript theme={null}
const response = await client.repayLoanSimple({
  loan: loanAddress,
  repayParams: {
    amount: 0,
    ledgerIndex: 0,
    repayAll: true,
  },
  strategy: strategyAddress,
});

await executeLoopscaleResponse(response);
```

### Parameters

| Parameter     | Type                                | Description                          |
| ------------- | ----------------------------------- | ------------------------------------ |
| `loan`        | `PublicKey \| string`               | Loopscale loan account               |
| `repayParams` | `{ amount, ledgerIndex, repayAll }` | Repayment details for the loan       |
| `strategy`    | `PublicKey \| string`               | Strategy used for the repayment flow |

A matching policy must exist before executing. See [Policy Builders](/developer-strategy-vaults/policy-builders#loopscale-policy). See also [Loopscale: Repay Loan](https://docs.loopscale.com/api-reference/transactions/borrow/repay-loan) for API details.

***

## Withdraw collateral

```typescript theme={null}
const response = await client.withdrawCollateral({
  loan: loanAddress,
  collateralMint: new PublicKey("..."),
  amount: 500_000_000,
  collateralIndex: 0,
  expectedLoanValues: {
    expectedApy: 0,
    expectedLqt: [0, 0, 0, 0, 0],
  },
});

await executeLoopscaleResponse(response);
```

### Parameters

| Parameter            | Type                                               | Description                              |
| -------------------- | -------------------------------------------------- | ---------------------------------------- |
| `loan`               | `PublicKey \| string`                              | Loopscale loan account                   |
| `collateralMint`     | `PublicKey \| string`                              | Mint to withdraw                         |
| `amount`             | `bigint \| number`                                 | Collateral amount to withdraw            |
| `collateralIndex`    | `number`                                           | Collateral slot to withdraw from         |
| `expectedLoanValues` | `{ expectedApy?: number; expectedLqt?: number[] }` | Loan-state hints required by the request |
| `assetIndexGuidance` | `number[]`                                         | Optional asset index hints               |

A matching policy must exist before executing. See [Policy Builders](/developer-strategy-vaults/policy-builders#loopscale-policy). See also [Loopscale: Withdraw Collateral](https://docs.loopscale.com/api-reference/transactions/borrow/withdraw-collateral) for API details.

***

## Close loan

```typescript theme={null}
const response = await client.closeLoan({
  loan: loanAddress,
});

await executeLoopscaleResponse(response);
```

### Parameters

| Parameter | Type                  | Description            |
| --------- | --------------------- | ---------------------- |
| `loan`    | `PublicKey \| string` | Loopscale loan account |

A matching policy must exist before executing. See [Policy Builders](/developer-strategy-vaults/policy-builders#loopscale-policy). See also [Loopscale: Close Loan](https://docs.loopscale.com/api-reference/transactions/borrow/close-loan) for API details.

***

## Practical notes

* `createStrategy(...)` can be executed directly from its raw response. Use `extractCreatedStrategyAddress(...)` only when you want to reference the created strategy later.
* `createLoan(...)` returns a raw response plus `loanAddress`, so you can construct the loan public key immediately.
* Only call `coSign(...)` for transactions flagged with `requiresLoopscaleCoSign === true`.
* Split lender-side strategy actions and borrower-side loan actions into separate Loopscale policies when you configure the vault.
