> For the complete documentation index, see [llms.txt](https://docs.selcier.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.selcier.xyz/build-on-selcier/supporting-selcier-tokens.md).

# Supporting Selcier tokens

Integration notes for handling Selcier Share Tokens on Robinhood Chain, written for wallet, venue, lending and data teams.

Existing Robinhood Chain infrastructure can take on Selcier Share Tokens with little effort. They use 18 decimals as ERC-20 tokens, offer price reads compatible with Chainlink, and share the multiplier and oracle conventions of Robinhood Stock Tokens. For most integrations, standard ERC-20 support plus a handful of additions is enough.

The sections below set out those additions, first in general and then by type of integration.

## How these tokens differ from a plain ERC-20

| Aspect               | Selcier Share Token                                                         | Plain ERC-20                                |
| -------------------- | --------------------------------------------------------------------------- | ------------------------------------------- |
| Transfers            | Go through only when `canTransfer` returns `OK` for the two parties         | Go through whenever the balance covers them |
| What a balance means | Raw units, which become shares after multiplying by `uiMultiplier() / 1e18` | Token units                                 |
| Price                | A dated, sourced Reference Valuation read from `ValuationOracle`            | Set by markets                              |
| Pausing              | A paused share class blocks all transfers                                   | Typically absent                            |
| Holders              | Only a wallet with a verified identity, linked for that company             | Whatever address                            |

Nothing else should surprise you: `balanceOf`, `transfer`, `approve`, `allowance`, `transferFrom` and the usual events work in the standard way.

## Simulate the transfer first

Share class rules run on-chain with each transfer, and breaking one causes a revert carrying a [transfer outcome code](/build-on-selcier/transfer-outcomes.md). A prior call to `canTransfer` spares users from signing a transaction that was never going to succeed.

```ts
const [ok, reasonCode] = await client.readContract({
  address: token,
  abi: shareTokenAbi,
  functionName: "canTransfer",
  args: [from, to, amount],
});
```

Where direct chain access is unavailable, turn to `POST /v1/transfers/check`. The answer matches, a plain-language message comes with it, and publishable keys can call it from a browser. For the portion of a balance able to move right now, read `unlockedBalanceOf(holder)`, which leaves out tokens that are frozen, unvested or inside a holding period.

## Apply the multiplier to balances

A split or similar corporate action updates `uiMultiplier` and leaves raw balances as they were, which is why approvals, pools and lending positions come through unaffected. The correct share count on screen is therefore your interface's job.

```ts
const shares = (rawBalance * multiplier) / 10n ** 18n; // still at 18 decimals
```

Avoid caching `uiMultiplier()` for long periods: either read it at display time or listen for `UIMultiplierUpdated`. Integrators always get at least 48 hours of warning, because a change is first announced by `MultiplierScheduled`. If you use the SDK, its `toDisplayAmount` helper handles the math.

Go in the opposite direction for user input: turn the typed share amount into raw units ahead of building the transaction.

## Reading prices

A `ValuationOracle` exists per share class and implements the read functions of the Chainlink `AggregatorV3Interface`, so code built around `latestRoundData()` needs no changes. Expect USD per share at 8 decimals. Following a split, the company publishes a valuation per post-split share, which means a price should be paired with the multiplier that applied on its `asOf` date.

```solidity
(, int256 price, , uint256 updatedAt, ) = AggregatorV3Interface(oracle).latestRoundData();
```

When you need more context, `latestValuation()` gives you four things: the price, the date it applies to, the supporting document's hash, and its source (`PRICED_ROUND`, `INDEPENDENT_VALUATION` or `WINDOW_CLEARING`).

{% hint style="warning" %}
Do not treat a Reference Valuation as a live market quote. A private company's figure changes only on three occasions (a funding round, an independent valuation or a Liquidity Window clear), and months can separate them. Display the source and date beside the price. For risk uses such as collateral value, set limits that reflect the age of the figure. [How a valuation gets on-chain](/fundamentals/valuation-publishing.md) has more.
{% endhint %}

## Reacting to a pause

During a pause, transfers revert with `TOKEN_PAUSED`, and the valuation oracle publishes nothing further while keeping its last value. Listen on the token for `Paused(reason)` and `Unpaused()`, and let your interface show the current state. A pause is common around a multiplier change, since it holds the oracle as well, and Robinhood Chain follows that same convention with its stock tokens.

## Notes for each integration type

### Wallet teams

* Present balances in shares, with the multiplier applied, next to the company and share class names.
* Call `canTransfer` while the send form is being completed, so any reason is visible ahead of signing.
* Keep the locked and unlocked figures separate.
* Add a link from each token to its [Explorer](https://explorer.selcier.xyz) page, where documents, supply and history live.

### Venue and AMM builders

Any pool or venue contract holding Selcier tokens has two requirements. It must have an identity registered in the company's `IdentityRegistry` with a valid `VENUE` claim, the claim data being the share token's address, and the issuer must opt in.

With the claim in place, the contract counts as an agent (`isAgent(venue)` returns true), so the token looks at the people on each side of a trade and not at the venue. Lacking it, anything sent to the venue reverts with `RECIPIENT_NOT_VERIFIED`.

AMM pools can rely on `PoolGate`, the Selcier hook that screens every liquidity provider and the end recipient of each swap. [Gated AMM pools](/markets-and-capital/gated-pools.md) explains how a venue requests a `VENUE` claim and how issuers turn this on.

Write to <hello@selcier.xyz> if you would like to list Selcier assets on a venue.

### Lending protocol teams

* A `VENUE` claim is needed on the contract that holds collateral, the same as for a pool.
* A liquidation can deliver tokens only to an eligible wallet, so run `canTransfer` for the liquidator before opening up a liquidation path.
* Build in pause handling: liquidation of a paused share class has to wait until it is unpaused.
* Choose staleness limits and collateral factors on the conservative side, in line with how seldom a Reference Valuation changes.

### Indexing and data teams

* Start indexing at the `CompanyDeployed` and `ShareClassDeployed` events from the factory, as covered in the [Chain event catalog](/build-on-selcier/chain-events.md).
* Keep raw balances in storage and bring in the multiplier when reading.
* Attach a source and date to any price you show.
* For metadata, a publishable key can call `GET /v1/contracts` and `GET /v1/valuations`.

## Naming these tokens

The right description for Selcier tokens is **issuer-sponsored stock tokens**: the company they represent is the one issuing them. Third-party stock tokens are something else, since they follow a company's price with no involvement from the company, and users should be able to tell which kind they hold. Take the company and share class names from the token metadata, and never call a Reference Valuation a market price.

## Trying it out

The sandbox on Robinhood Chain testnet (`46630`) supports end-to-end testing of any integration. Share classes, test identities holding any claims you like, and venue identities can all be created there. [Your first integration](/build-on-selcier/first-integration.md) is the place to begin.


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.selcier.xyz/build-on-selcier/supporting-selcier-tokens.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
