# Create a Loan Broker

This tutorial shows you how to create a [LoanBroker](/docs/references/protocol/ledger-data/ledger-entry-types/loanbroker) on the XRP Ledger using a private vault. A loan broker creates and manages loans, and also manages the first-loss capital for a connected single asset vault.

LendingProtocol
## Goals

By the end of this tutorial, you will be able to:

- Create a **loan broker** linked to a private single asset vault.
- Configure loan broker parameters, such as a management fee rate.
- Retrieve the loan broker ID and pseudo-account.


## Prerequisites

To complete this tutorial, you should:

- Have a basic understanding of the XRP Ledger.
- Have an XRP Ledger client library set up in your development environment. This page provides examples for the following:
  - **JavaScript** with the [xrpl.js library](https://github.com/XRPLF/xrpl.js). See [Get Started Using JavaScript](/docs/tutorials/get-started/get-started-javascript) for setup steps.
  - **Python** with the [xrpl-py library](https://github.com/XRPLF/xrpl-py). See [Get Started Using Python](/docs/tutorials/get-started/get-started-python) for setup steps.
  - **Go** with the [xrpl-go library](https://github.com/XRPLF/xrpl-go). See [Get Started Using Go](/docs/tutorials/get-started/get-started-go) for setup steps.


## Source Code

You can find the complete source code for this tutorial's examples in the code samples section of this website's repository.

## Steps

### 1. Install dependencies

JavaScript
From the code sample folder, use `npm` to install dependencies.


```bash
npm install xrpl
```

Python
From the code sample folder, set up a virtual environment and use `pip` to install dependencies.


```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

Go
From the code sample folder, use `go` to install dependencies.


```bash
go mod tidy
```

### 2. Set up client and accounts

To get started, import the necessary libraries and instantiate a client to connect to the XRPL. This example imports:

JavaScript
- `xrpl`: Used for XRPL client connection, transaction submission, and wallet handling.
- `fs` and `child_process`: Used to run tutorial set up scripts.



```js
// IMPORTANT: This example creates a loan broker using an existing account
// that has already created a PRIVATE vault.
// If you want to create a loan broker for a PUBLIC vault, you can replace the vaultID
// and loanBroker values with your own.

import fs from 'fs'
import { execSync } from 'child_process'
import xrpl from 'xrpl'

// Connect to the network ----------------------
const client = new xrpl.Client('wss://s.devnet.rippletest.net:51233')
await client.connect()
```

Python
- `xrpl`: Used for XRPL client connection, transaction submission, and wallet handling.
- `json`: Used for loading and formatting JSON data.
- `os`, `subprocess`, and `sys`: Used to run tutorial set up scripts.



```py
# IMPORTANT: This example creates a loan broker using an existing account
# that has already created a PRIVATE vault.
# If you want to create a loan broker for a PUBLIC vault, you can replace the vault_id
# and loan_broker values with your own.

import json
import os
import subprocess
import sys

from xrpl.clients import JsonRpcClient
from xrpl.models import LoanBrokerSet
from xrpl.transaction import submit_and_wait
from xrpl.wallet import Wallet

# Set up client ----------------------
client = JsonRpcClient("https://s.devnet.rippletest.net:51234")
```

Go
- `xrpl-go`: Used for XRPL client connection, transaction submission, and wallet handling.
- `encoding/json` and `fmt`: Used for formatting and printing results to the console.
- `os` and `os/exec`: Used to run tutorial set up scripts.



```go
// IMPORTANT: This example creates a loan broker using an existing account
// that has already created a PRIVATE vault.
// If you want to create a loan broker for a PUBLIC vault, you can replace the vaultID
// and loanBroker values with your own.

package main

import (
	"encoding/json"
	"fmt"
	"os"
	"os/exec"

	"github.com/Peersyst/xrpl-go/xrpl/transaction"
	"github.com/Peersyst/xrpl-go/xrpl/transaction/types"
	"github.com/Peersyst/xrpl-go/xrpl/wallet"
	"github.com/Peersyst/xrpl-go/xrpl/websocket"
	wstypes "github.com/Peersyst/xrpl-go/xrpl/websocket/types"
)

func main() {
	// Connect to the network ----------------------
	client := websocket.NewClient(
		websocket.NewClientConfig().
			WithHost("wss://s.devnet.rippletest.net:51233"),
	)
	defer client.Disconnect()

	if err := client.Connect(); err != nil {
		panic(err)
	}
```

Next, load the vault owner account and vault ID. The vault owner will also be the loan broker.

JavaScript

```js
// This step checks for the necessary setup data to run the lending protocol tutorials.
// If missing, lendingSetup.js will generate the data.
if (!fs.existsSync('lendingSetup.json')) {
  console.log(`\n=== Lending tutorial data doesn't exist. Running setup script... ===\n`)
  execSync('node lendingSetup.js', { stdio: 'inherit' })
}

// Load preconfigured accounts and VaultID.
const setupData = JSON.parse(fs.readFileSync('lendingSetup.json', 'utf8'))

// You can replace these values with your own
const loanBroker = xrpl.Wallet.fromSeed(setupData.loanBroker.seed)
const vaultID = setupData.vaultID

console.log(`\nLoan broker/vault owner address: ${loanBroker.address}`)
console.log(`Vault ID: ${vaultID}`)
```

This example uses preconfigured accounts and vault data from the `lendingSetup.js` script, but you can replace `loanBroker` and `vaultID` with your own values.

Python

```py
# This step checks for the necessary setup data to run the lending protocol tutorials.
# If missing, lending_setup.py will generate the data.
if not os.path.exists("lending_setup.json"):
    print("\n=== Lending tutorial data doesn't exist. Running setup script... ===\n")
    subprocess.run([sys.executable, "lending_setup.py"], check=True)

# Load preconfigured accounts and vault_id.
with open("lending_setup.json") as f:
    setup_data = json.load(f)

# You can replace these values with your own.
loan_broker = Wallet.from_seed(setup_data["loan_broker"]["seed"])
vault_id = setup_data["vault_id"]

print(f"\nLoan broker/vault owner address: {loan_broker.address}")
print(f"Vault ID: {vault_id}")
```

This example uses preconfigured accounts and vault data from the `lending_setup.py` script, but you can replace `loan_broker` and `vault_id` with your own values.

Go

```go
	// Check for setup data; run lending-setup if missing
	if _, err := os.Stat("lending-setup.json"); os.IsNotExist(err) {
		fmt.Printf("\n=== Lending tutorial data doesn't exist. Running setup script... ===\n\n")
		cmd := exec.Command("go", "run", "./lending-setup")
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		if err := cmd.Run(); err != nil {
			panic(err)
		}
	}

	// Load preconfigured accounts and VaultID
	data, err := os.ReadFile("lending-setup.json")
	if err != nil {
		panic(err)
	}
	var setup map[string]any
	if err := json.Unmarshal(data, &setup); err != nil {
		panic(err)
	}

	// You can replace these values with your own
	loanBrokerWallet, err := wallet.FromSecret(setup["loanBroker"].(map[string]any)["seed"].(string))
	if err != nil {
		panic(err)
	}
	vaultID := setup["vaultID"].(string)

	fmt.Printf("\nLoan broker/vault owner address: %s\n", loanBrokerWallet.ClassicAddress)
	fmt.Printf("Vault ID: %s\n", vaultID)
```

This example uses preconfigured accounts and vault data from the `lending-setup` script, but you can replace `loanBrokerWallet` and `vaultID` with your own values.

### 3. Prepare LoanBrokerSet transaction

Create the [LoanBrokerSet transaction](/docs/references/protocol/transactions/types/loanbrokerset) object.

JavaScript

```js
// Prepare LoanBrokerSet transaction ----------------------
console.log(`\n=== Preparing LoanBrokerSet transaction ===\n`)
const loanBrokerSetTx = {
  TransactionType: 'LoanBrokerSet',
  Account: loanBroker.address,
  VaultID: vaultID,
  ManagementFeeRate: 1000
}

// Validate the transaction structure before submitting
xrpl.validate(loanBrokerSetTx)
console.log(JSON.stringify(loanBrokerSetTx, null, 2))
```

Python

```py
# Prepare LoanBrokerSet transaction ----------------------
print("\n=== Preparing LoanBrokerSet transaction ===\n")
loan_broker_set_tx = LoanBrokerSet(
    account=loan_broker.address,
    vault_id=vault_id,
    management_fee_rate=1000,
)

print(json.dumps(loan_broker_set_tx.to_xrpl(), indent=2))
```

Go

```go
	// Prepare LoanBrokerSet transaction ----------------------
	fmt.Printf("\n=== Preparing LoanBrokerSet transaction ===\n\n")
	mgmtFeeRate := types.InterestRate(1000)
	loanBrokerSetTx := transaction.LoanBrokerSet{
		BaseTx: transaction.BaseTx{
			Account: loanBrokerWallet.ClassicAddress,
		},
		VaultID:           vaultID,
		ManagementFeeRate: &mgmtFeeRate,
	}

	// Flatten() converts the struct to a map and adds the TransactionType field
	flatLoanBrokerSetTx := loanBrokerSetTx.Flatten()
	loanBrokerSetTxJSON, _ := json.MarshalIndent(flatLoanBrokerSetTx, "", "  ")
	fmt.Printf("%s\n", string(loanBrokerSetTxJSON))
```

The management fee rate is set in 1/10th basis points. A value of `1000` equals 1% (100 basis points).

### 4. Submit LoanBrokerSet transaction

Sign and submit the `LoanBrokerSet` transaction to the XRP Ledger.

JavaScript

```js
// Submit, sign, and wait for validation ----------------------
console.log(`\n=== Submitting LoanBrokerSet transaction ===\n`)
const submitResponse = await client.submitAndWait(loanBrokerSetTx, {
  wallet: loanBroker,
  autofill: true
})
if (submitResponse.result.meta.TransactionResult !== 'tesSUCCESS') {
  const resultCode = submitResponse.result.meta.TransactionResult
  console.error('Error: Unable to create loan broker:', resultCode)
  await client.disconnect()
  process.exit(1)
}
console.log('Loan broker created successfully!')
```

Python

```py
# Submit, sign, and wait for validation ----------------------
print("\n=== Submitting LoanBrokerSet transaction ===\n")
submit_response = submit_and_wait(loan_broker_set_tx, client, loan_broker)

if submit_response.result["meta"]["TransactionResult"] != "tesSUCCESS":
    result_code = submit_response.result["meta"]["TransactionResult"]
    print(f"Error: Unable to create loan broker: {result_code}")
    sys.exit(1)

print("Loan broker created successfully!")
```

Go

```go
	// Submit, sign, and wait for validation ----------------------
	fmt.Printf("\n=== Submitting LoanBrokerSet transaction ===\n\n")
	loanBrokerSetResponse, err := client.SubmitTxAndWait(flatLoanBrokerSetTx, &wstypes.SubmitOptions{
		Autofill: true,
		Wallet:   &loanBrokerWallet,
	})
	if err != nil {
		panic(err)
	}

	if loanBrokerSetResponse.Meta.TransactionResult != "tesSUCCESS" {
		fmt.Printf("Error: Unable to create loan broker: %s\n", loanBrokerSetResponse.Meta.TransactionResult)
		os.Exit(1)
	}
	fmt.Printf("Loan broker created successfully!\n")
```

Verify that the transaction succeeded by checking for a `tesSUCCESS` result code.

### 5. Get loan broker information

Retrieve the loan broker's information from the transaction result by checking for the `LoanBroker` entry in the transaction metadata.

JavaScript

```js
// Extract loan broker information from the transaction result
console.log(`\n=== Loan Broker Information ===\n`)
const loanBrokerNode = submitResponse.result.meta.AffectedNodes.find(node =>
  node.CreatedNode?.LedgerEntryType === 'LoanBroker'
)
console.log(`LoanBroker ID: ${loanBrokerNode.CreatedNode.LedgerIndex}`)
console.log(`LoanBroker Psuedo-Account Address: ${loanBrokerNode.CreatedNode.NewFields.Account}`)

await client.disconnect()
```

Python

```py
# Extract loan broker information from the transaction result
print("\n=== Loan Broker Information ===\n")
loan_broker_node = next(
    node for node in submit_response.result["meta"]["AffectedNodes"]
    if node.get("CreatedNode", {}).get("LedgerEntryType") == "LoanBroker"
)
print(f"LoanBroker ID: {loan_broker_node['CreatedNode']['LedgerIndex']}")
print(f"LoanBroker Psuedo-Account Address: {loan_broker_node['CreatedNode']['NewFields']['Account']}")
```

Go

```go
	// Extract loan broker information from the transaction result
	fmt.Printf("\n=== Loan Broker Information ===\n\n")
	for _, node := range loanBrokerSetResponse.Meta.AffectedNodes {
		if node.CreatedNode != nil && node.CreatedNode.LedgerEntryType == "LoanBroker" {
			fmt.Printf("LoanBroker ID: %s\n", node.CreatedNode.LedgerIndex)
			fmt.Printf("LoanBroker Pseudo-Account Address: %s\n", node.CreatedNode.NewFields["Account"])
			break
		}
	}
}
```

The loan broker pseudo-account is a special account that holds first-loss capital.

## See Also

**Concepts**:

- [Lending Protocol](/docs/concepts/tokens/lending-protocol)
- [Single Asset Vault](/es-es/docs/concepts/tokens/single-asset-vaults)


**Tutorials**:

- [Create a Single Asset Vault](/es-es/docs/tutorials/defi/lending/use-single-asset-vaults/create-a-single-asset-vault)
- [Deposit and Withdraw First-Loss Capital](/es-es/docs/tutorials/defi/lending/use-the-lending-protocol/deposit-and-withdraw-cover)
- [Create a Loan](/es-es/docs/tutorials/defi/lending/use-the-lending-protocol/create-a-loan)


**References**:

- [LoanBrokerSet transaction](/docs/references/protocol/transactions/types/loanbrokerset)