Skip to main content
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

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, index.ts.