> For the complete documentation index, see [llms.txt](https://docs.holonym.id/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.holonym.id/stellar.md).

# Stellar

Users can opt to receive SBTs on Stellar. See [Using Human ID with Stellar](/for-users/using-with-stellar.md) for user-facing instructions.

### Off-chain

Use the Stellar SDK to simulate a read transaction to get the user's SBT.

```typescript
import {
  Horizon,
  rpc,
  TransactionBuilder,
  Networks,
  Contract,
  scValToNative,
  nativeToScVal,
} from '@stellar/stellar-sdk'

/// Types ///
type StellarSbt = {
  action_nullifier: bigint,
  circuit_id: bigint,
  expiry: bigint,
  id: bigint,
  minter: string, // Stellar address
  public_values: Array<bigint>,
  recipient: string, // Stellar address
  revoked: boolean
}
type StellarSbtStatus = 'valid' | 'expired' | 'revoked' | 'none'
type GetStellarSBTRetVal = {
  sbt?: StellarSbt
  status: StellarSbtStatus
}

/// Constants ///
const horizonServerUrl = 'https://horizon.stellar.org'
const sorobanRpcUrl = 'https://mainnet.sorobanrpc.com'
const stellarSBTContractAddress = 'CCNTHEVSWNDOQAMXXHFOLQIXWUINUPTJIM6AXFSKODNVXWA4N7XV3AI5'

/// Get SBT ///
async function getStellarSBTByAddress(
  address: string,
  circuitId: string
): Promise<GetStellarSBTRetVal | null> {
  const sorobanServer = new rpc.Server(sorobanRpcUrl)
  const userAccount = await sorobanServer.getAccount(address)
  const contract = new Contract(stellarSBTContractAddress)

  const operation = contract.call(
    'get_sbt',
    nativeToScVal(address, { type: 'address' }),
    nativeToScVal(circuitId, { type: 'u256' })
  )

  const transaction = new TransactionBuilder(userAccount, {
    Networks.PUBLIC,
    fee: '100',
  })
    .addOperation(operation)
    .setTimeout(60)
    .build()

  const simulationResponse = await sorobanServer.simulateTransaction(transaction)
  const parsed = rpc.parseRawSimulation(simulationResponse)

  // Happy path. User has the desired SBT.
  if (rpc.Api.isSimulationSuccess(simulationResponse)) {
    const _parsed = parsed as rpc.Api.SimulateTransactionSuccessResponse

    if (!_parsed.result) {
      throw new Error('Unexpected: Could not get "result" field from parsed Stellar transaction simulation for SBT query')
    }

    const sbt = scValToNative(_parsed.result?.retval)

    return {
      sbt,
      status: 'valid'
    }
  }
  // Error cases. User does not have the SBT.
  else if (rpc.Api.isSimulationError(simulationResponse)) {
    const _parsed = parsed as rpc.Api.SimulateTransactionErrorResponse

    // Error code 1 is "SBT not found"
    if (_parsed.error.includes('HostError: Error(Contract, #1)')) {
      return { status: 'none' }
    }

    // Error code 5 is "SBT revoked"
    if (_parsed.error.includes('HostError: Error(Contract, #5)')) {
      return { status: 'revoked' }
    }

    // Error code 6 is "SBT expired"
    if (_parsed.error.includes('HostError: Error(Contract, #6)')) {
      return { status: 'expired' }
    }

    throw new Error(`Stellar transaction simulation for SBT query failed: ${_parsed.error}`)
  } else {
    throw new Error('Unexpected: Stellar transaction simulation for SBT query returned an unexpected response')
  }
}

```

### On-chain (Soroban)

#### 1. Fetch the wasm for the Human ID SBT contract.

```bash
soroban contract fetch --id CCNTHEVSWNDOQAMXXHFOLQIXWUINUPTJIM6AXFSKODNVXWA4N7XV3AI5 -o ./human_id_sbt_contract.wasm --network mainnet --network-passphrase "Public Global Stellar Network ; September 2015" --rpc-url https://mainnet.sorobanrpc.com
```

#### 2. Incorporate into your Soroban contract.

This example contract has a `get_sbt` function that simply wraps the function from the SBT contract.

Check out the full [Human ID SBT contract here](https://github.com/holonym-foundation/id-hub-contracts/blob/main/contracts/stellar/human-id/contracts/sbt/src/lib.rs).

For the list of circuit IDs, see [here](https://github.com/holonym-foundation/holonym-api/blob/235c57310781e66d19cf5ad675132088d266da87/src/constants/misc.js#L18C1-L25C72).

```rust
#![no_std]
use soroban_sdk::{contract, contractimpl, Env, Address, U256};

mod human_id_sbt_contract {
    soroban_sdk::contractimport!(
        file = "../../human_id_sbt_contract.wasm"
    );
}

#[contract]
pub struct MyContract;

#[contractimpl]
impl MyContract {
    /// * `recipient` - The address of the SBT recipient.
    /// * `circuit_id` - This determines the type of SBT to look up. For example, KYC, ePassport, and phone number
    ///   SBTs each have a different circuit ID.
    pub fn get_sbt(env: Env, recipient: Address, circuit_id: U256) -> human_id_sbt_contract::SBT {
        let human_id_sbt_contract_addr = Address::from_str(&env, "CCNTHEVSWNDOQAMXXHFOLQIXWUINUPTJIM6AXFSKODNVXWA4N7XV3AI5");
        let human_id_sbt_client = human_id_sbt_contract::Client::new(&env, &human_id_sbt_contract_addr);

        human_id_sbt_client.get_sbt(&recipient, &circuit_id)
    }
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.holonym.id/stellar.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
