# Example wallet

One wallet, live: press Sample wallet to read its holdings and benefits from Yutai and see them drawn by the SDK, with the code that asks for them.

## The example

Nothing is read when the page opens. The Sample wallet press asks Yutai's keyless documentation read for the wallet shown, so a signed-out visitor sees its holdings without a key being set. The press asks for a fresh answer at most once a minute, so the read can stand up to a minute behind Yutai's answer now. Pick the sample wallet or paste an address of your own: a pasted address stays in the form and never lands in the page's address. The pane beside the render carries the same answer as the JSON Yutai returned, and the keyed call for the same wallet: point at or focus a company row on either side, and its blocks on the other side light.

Want to connect your own wallet? [Open the Yutai app](https://app.yutai.com/app)

Press Sample wallet to read the approved sample wallet's holdings and benefits from Yutai, or paste an address of your own. Nothing is read until you press.

## Read, render, claim

Three steps take the wallet's answer from Yutai to a person's screen.

1. ### Read

   Your page asks Yutai for the wallet's holdings and benefits with one keyed call added to your server. The call below is the one to make.
2. ### Render

   Hand the answer to the SDK's module element with read-only set: it draws the shared holdings table in the holder app's look, one row per company with its shares, days held, tier and the wallet's own state, the filter pressing in place, and the Ready to claim chip opening the Yutai app where a wallet can prove itself.
3. ### Claim

   A benefit the wallet reaches is claimed in the holder's own Yutai app or in the distributor's app, where the wallet signs. This page has no claim control, so nobody signs here.

## The calls

The printed call is the keyed call a distributor makes: it connects the SDK's client and asks the eligibility read for the sample wallet, with a placeholder where the key stands. This page's own live read does not use that key: it asks Yutai's keyless documentation read for the same wallet, so the example above draws without a key being set. The key never reaches your browser.

The keyed call a distributor makes

```
import { connectDistributorApi } from "@yutai/sdk-web";

const client = connectDistributorApi({ base: "https://api.yutai.com", key: "ytk_your-key" });

const answer = await client.askEligibility(["0x5aaf3fd78c9f0bd2c39c3b8b1f443ec8d1a5244b"]);
```

- `GET /v1/eligibility` the tokens a wallet holds and the benefits they reach: the keyed call the printed snippet makes; the press's answer, once Sample wallet is pressed, and the paste box's read ask the docs route's keyless twin of the same answer
- `POST /v1/claims/challenge` the words the wallet signs before a claim, printed for reference: nothing on this page signs
- `POST /v1/claims` the claim recorded on that proof, printed for reference: claiming happens in the holder's or the distributor's own app
- `GET /v1/claims/{id}` the claim's own state, in the words the read answers, printed for reference
- `POST /v1/connect/sessions` the Connect session the example's press creates on the server, under the demo key
- `GET /v1/connect/sessions/{id}` the session's own standing, read after the hosted flow returns

The claim flow is printed for reference: a benefit the sample wallet reaches is claimed in the holder's Yutai app or the distributor's app, where the wallet signs. Nothing on this page signs or claims, so no press stands beneath it.

The claim flow, printed for reference

```
import { connectDistributorApi, refusedSentenceOf } from "@yutai/sdk-web";

const key = "ytk_your-key";
const client = connectDistributorApi({ base: "https://api.yutai.com", key });
const headers = { Authorization: `Bearer ${key}`, Accept: "application/json" };

// The words the wallet signs, before the claim is asked.
const challenge = await client.askClaimChallenge(benefitId, [wallet]);
const signature = await wallet.signMessage(challenge.message);

// The claim, recorded on that proof.
const answer = await client.askClaim({ benefitId, wallet, nonce: challenge.nonce, signature });
if (answer.status !== "claimed") throw new Error(refusedSentenceOf(answer.reason));

// The claim's own state, in the words the read answers.
const claimRead = await fetch(`https://api.yutai.com/v1/claims/${answer.claimId}`, { headers });
if (!claimRead.ok) throw new Error("The call was refused with HTTP " + claimRead.status);
const claim = await claimRead.json();
```

## The Connect flow

A holder who has not linked a card can link one here. The press asks this page's server for a Connect session on the docs demo key, opens the hosted flow with the SDK's one door, and then reads the session's standing on the server: the standing is what the page draws, never the browser's word alone. On a phone the hosted page moves the whole page and returns to this address; the session id waits in the browser for that return, and the same server read answers it. When the demo key is not set, or the demo profile does not allow this page's return address, the press answers in Yutai's own words and nothing is opened.

The code the press runs: the create on the server, the one browser door, and the read that decides what is granted.

The Connect flow the example runs

```
import { connect, connectDistributorApi } from "@yutai/sdk-web";

// On your server, never in the browser.
const api = connectDistributorApi({ base: "https://api.yutai.com", key: "ytk_your-key" });
const session = await api.createConnectSession({
  externalRef: "example-wallet-customer",
  returnUrl: "https://wallet.example/yutai/return",
  view: "consent",
});

// In the browser: the one door opens the hosted page and answers its standing.
const result = await connect({ sessionUrl: session.connectUrl });

// Back on your server: read the session before you grant anything.
const standing = await api.readConnectSession(result.session);
```
