# Encryption in browser with wallet & extension

### Creating a secret NFT in a browser environment

This section provides a comprehensive guide on creating a Secret NFT on the Ternoa chain without using a SEED to retrieve the signer keyring. To successfully follow this process, it is recommended that you have a basic understanding of the concepts explained step by step in the following pages:

* [Introduction to TEE clusters](/build-1/javascript/privacy-protocols/tee-privacy-and-encryption/handling-clusters.md)
* [Generate keys & Encryption](/build-1/javascript/privacy-protocols/tee-privacy-and-encryption/generating-keys-and-encrypt.md)
* [Storing a private key on the Ternoa SGX Enclaves](/build-1/javascript/privacy-protocols/tee-privacy-and-encryption/storing-encrypted-key-to-clusters.md)

Suppose this is your first time interacting with the Ternoa chain in a browser environment and using a wallet or extension to sign a transaction. In that case, it is advisable to begin with a simpler code example and read through this section beforehand.

{% hint style="info" %}
We also assume you are familiar with the Ternoa IPFS client. Use the Ternoa IPFS node endpoint, with a key generated from our [key generator](https://ipfs-key-manager-git-dev-ternoa.vercel.app/), or your own storage provider. Read more about the Ternoa IPFS client. Read more about storage options.&#x20;
{% endhint %}

#### Utilizing Polkadot extension, Next.js, and TypeScript:

In the following code snippet, we will walk through a step-by-step process for a use case to create a Secret NFT on the chain. This involves using the @polkadot/extension-dapp and uploading your files and metadata to IPFS.

It's important to note that this solution is not the only option available. Feel free to choose any provider that best suits your dApp and adjust your code accordingly to match your technical stack.

This code snippet is specifically designed to function within a Next.js environment. Depending on Next.js server-side component rules, you may need to make slight adaptations when importing the @polkadot/extension-dapp extension library to work seamlessly in your JavaScript environment.

```typescript
import { SecretNFTResponse } from "@/components/base/Forms/SecretNFT/types";
import {
  NFTCreatedEvent,
  NftMetadataType,
  SecretAddedToNFTEvent,
  TernoaIPFS,
  WaitUntil,
  createSecretNftTx,
  generatePGPKeys,
  getEnclaveHealthStatus,
  getFirstPublicClusterAvailable,
  getRawApi,
  prepareAndStoreKeyShares,
  query,
  secretNftEncryptAndUploadFile,
  submitTxBlocking,
} from "ternoa-js";

export const mintSecretNFT = async (
  address: string,
  nftFile: File,
  nftMetadata: NftMetadataType,
  secretNftFile: File,
  secretNftMetadata: NftMetadataType,
  ipfsClient: TernoaIPFS,
  royalty: number,
  collection: number | undefined,
  isSoulbound: boolean
): Promise<SecretNFTResponse> => {
  try {
    const clusterId = await getFirstPublicClusterAvailable();
    await getEnclaveHealthStatus(clusterId);

    console.log("Uploading content on IPFS.");

    const { privateKey, publicKey } = await generatePGPKeys();
    const { Hash: offchainDataHash } = await ipfsClient.storeNFT(
      nftFile,
      nftMetadata
    );
    const { Hash: secretOffchainDataHash } =
      await secretNftEncryptAndUploadFile(
        secretNftFile,
        publicKey,
        ipfsClient,
        secretNftMetadata
      );

    console.log(
      "USER_ACTION: Sign transaction with your extension to create your secret NFT."
    );

    const txHex = await createSecretNftTx(
      offchainDataHash,
      secretOffchainDataHash,
      royalty,
      collection,
      isSoulbound
    );

    const nonce = (
      (await query("system", "account", [address])) as any
    ).nonce.toNumber();

    const { web3FromAddress } = await import("@polkadot/extension-dapp");
    const injector = (await web3FromAddress(address)) as Record<string, any>;
    const signer = injector?.signer;

    const api = getRawApi();

    const signedTx = (
      await api.tx(txHex).signAsync(address, { nonce, signer })
    ).toHex();

    console.log("Submitting transaction to the Ternoa chain.");

    const { events, blockInfo, txHash } = await submitTxBlocking(
      signedTx,
      WaitUntil.BlockInclusion
    );

    const nftEvent = events.findEventOrThrow(NFTCreatedEvent);
    const secretNftEvent = events.findEventOrThrow(SecretAddedToNFTEvent);

    console.log(
      "USER_ACTION: Sign transaction with your extension to securize your content and upload key on Ternoa SGX clusters."
    );

    const teeRes = await prepareAndStoreKeyShares(
      privateKey,
      address,
      nftEvent.nftId,
      "secret",
      injector,
      clusterId
    );

    return {
      event: secretNftEvent,
      clusterResponse: teeRes,
      blockInfo,
      txHash,
    };
  } catch (error) {
    console.log(error);
    const errorDescription = `SECRET_NFT_MINT_ERROR: ${
      error instanceof Error ? error.message : JSON.stringify(error)
    }`;
    throw new Error(errorDescription);
  }
};
```

*We suggest breaking down certain portions of this function into multiple modular and reusable atomic functions. This example illustrates a comprehensive and complete workflow to enhance comprehension.*


---

# Agent Instructions: 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:

```
GET https://docs.ternoa.network/build-1/javascript/privacy-protocols/tee-privacy-and-encryption/encryption-in-browser-with-wallet-and-extension.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
