> ## Documentation Index
> Fetch the complete documentation index at: https://trust-link-tsn.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# TIN V1 SDK: creation and owner recovery

> Current SDK helpers for private TIN V1 issuance, owner recovery, and staged creation.

The `@trustlink/tsn-sdk/tins` module implements the current private TIN V1 contract. TINs are generated by the trusted issuer; the TIP program verifies owner authorization and creates a registry account from the lookup commitment. The program does not assign a TIN.

## Issuance boundaries

* Generate the ten-digit TIN and derive its lookup commitment in the trusted issuer using a high-entropy `TINS_LOOKUP_SECRET`. The same value is configured on the trusted Node. Never send it to browser code, Receiver, or Cranker.
* Encrypt the TIN and display name with `createTinV1IdentityEnvelope` in the trusted issuer.
* In the owner's browser, request a wallet signature over `buildTinV1OwnerRecoveryMessage` and create a V4 owner-recovery envelope with `createTinV1OwnerRecoveryEnvelope`. Keep the recovery signature local; it is key material for decrypting the TIN.
* Build the owner-authorized intent with `buildTinV1Creation`, sign `buildTinOwnerIntentMessage(prepared.intentHash)`, then submit through Receiver with `submitTinV1Creation`.
* Do not report issuance complete until the Cranker transaction is confirmed.

## Local owner recovery

```ts theme={null}
import {
  buildTinV1OwnerRecoveryMessage,
  createTinV1OwnerRecoveryEnvelope,
  decryptTinV1OwnerRecoveryEnvelope,
  getTinV1OwnerRecoveryEnvelope,
} from "@trustlink/tsn-sdk/tins";

const recoveryMessage = buildTinV1OwnerRecoveryMessage(ownerPublicKey, programId);
const recoverySignature = await wallet.signMessage(recoveryMessage);

// Run in the owner's browser. Submit only the ciphertext to the issuer.
const encryptedTinRecovery = await createTinV1OwnerRecoveryEnvelope({
  tin,
  displayName,
  owner: ownerPublicKey,
  programId,
  signature: recoverySignature,
});

// On a later connection, fetch the owner-indexed PDA and decrypt locally.
const envelope = await getTinV1OwnerRecoveryEnvelope({
  connection,
  ownerPubkey: ownerPublicKey,
  programId,
});
if (envelope) {
  const identity = await decryptTinV1OwnerRecoveryEnvelope({
    encryptedEnvelope: envelope,
    owner: ownerPublicKey,
    programId,
    signature: await wallet.signMessage(recoveryMessage),
  });
}
```

The recovery signature and decrypted identity must remain on the owner's device. Newly created records use the `TSNTIN04` JSON envelope. The SDK's decryptor retains read-only `TSNTIN02` and `TSNTIN03` support for recovery records created by older versions; creation never emits those formats.

## TIN V1 creation and staging

`buildTinV1Creation` validates and hashes the versioned GPRU ElGamal public key, its commitment, and the TIP policy commitment. The owner SDK derives the key from the master seed with Solana's `@solana/zk-sdk`; it never sends the seed in the creation request. `serializeTinV1CreationParams` emits the program instruction data. If the complete transaction does not fit Solana's packet limit, use the staged-instruction serializers for begin, bounded chunks, and finalization; the SDK's `submitTinV1Creation` sends the owner-authorized payload to Receiver and does not submit directly to Solana. New TIP registry accounts use schema version 1 and omit the legacy NaCl key and stored TIP root.

`getTinV1CreationStagingPda` derives the temporary creation PDA.
`getTinV1OwnerRecoveryPda` derives the one-per-owner recovery PDA from the
`tin-v1-owner-recovery` seed and owner wallet public key. The TIN Registrar
program creates it alongside the main registry account. It stores the owner
public key and encrypted TIN recovery envelope; the main registry account is a
separate account and has no standalone owner-public-key field. Newly created
master-seed envelopes omit `ownerPublicKey`; previously created on-chain
envelopes may still expose it in plaintext. On wallet recovery, the SDK derives
this PDA, fetches the envelope,
and decrypts it locally after the owner signs the recovery message.

## Lookup commitment

`createTinV1IdentityEnvelope` takes `tin`, `displayName`, and `lookupSecret`, returning `lookupCommitment` and `encryptedIdentityEnvelope`. The secret must contain at least 16 bytes and remain within trusted issuer/Node configuration. There is no public all-zero lookup-secret fallback and no SDK legacy-account scan or `resolveTinRoute` API.

Source: [`tins.ts`](https://github.com/Trustlink-Labs/TSN-Protocol/blob/main/tsn-protocol/sdks/tsn-sdk/src/tins.ts), [`index.ts`](https://github.com/Trustlink-Labs/TSN-Protocol/blob/main/tsn-protocol/sdks/tsn-sdk/src/index.ts).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.