# issue

In this tutorial, you will learn how to send a VC to a specific 'holder'. The process of sending VC is VC Issue mode.

> Complete code example: [zkid-sdk-example /src/issue/issue.ts](https://github.com/zCloak-Network/zkid-sdk-example/blob/sdk-v2/src/issue/issue.ts)

## Tutorial

1. Initialize @noble cryptographic library and wasm;

```typescript
await initCrypto();
```

2. Get DID object of holder and attester;

```typescript
// get holder DID from DidDocument
const holderDidDoc = await resolver.resolve(holderDidUrl);
const holder = fromDidDocument(holderDidDoc);

// get attester DID from DID-Keys-file
const keyring = new Keyring();
const json = readDidKeysFile();
const password = "12345678"; // password to decrypt your DID-keys-file
const attester = restore(keyring, json, password);
  
// src/utils/resolverHelper.ts
export const resolver = new ArweaveDidResolver();

// src/utils/didHelper.ts
export function readDidKeysFile() {
  const attesterKeysFile = fs.readFileSync(
    path.resolve(__dirname, "../../attester-DID-keys-file.json"),
    { encoding: "utf-8" }
  );
  return JSON.parse(attesterKeysFile) as DidKeys$Json;
}
```

In the above process, the use of the following three APIs is mainly involved:

* Get resolver object, using `resolve` method get DID document from DID URL; The `resolver` can be some APIs parameters. For this kind of API, developers should explicitly specify `resolver` in their use, especially if you are developing in our development environment. This is because our `resolver` connects to the production environment by default, and if you don't specify a `resolver`, it may occurs the DID Method won't be found problem.

```typescript
const resolver = new ArweaveDidResolver();
const holderDidDoc = await resolver.resolve(holderDidUrl);
```

* Recover DID object by DID Document. The corresponding method is `fromDidDocument`. The DID document is obtained through the resolver's `resolve` interface.

```typescript
fromDidDocument(document: DidDocument, keyring?: KeyringInstance)
```

* Recover DID object by DID-keys-file. The corresponding method is `restore`. This method recovers DID object by inputing corresponding DID-keys-file contents and password where the password parameter is the password set when backing up the DID-keys-file;

```typescript
 restore(keyring: Keyring, json: DidKeys$Json, password: string)
```

tips: In addition to recovering the DID using the above methods, we also provide an API to recover the DID via mnemonics:

```typescript
fromMnemonic(keyring: KeyringInstance, mnemonic: string, signingKeyType?: 'ecdsa' | 'ed25519', index?: number)
```

3. Get ctype object from ctype hash;

```typescript
const ctype: CType = await getCtypeFromHash(ctypeHash);

// src/utils/ctypeHelper.ts
export async function getCtypeFromHash(
  hash: string | undefined,
  url = process.env.BASE_URL
): Promise<CType> {
  if (hash === undefined) {
    throw new Error("ctype hash undefined !!!");
  }

  const res = await axios.get(`${url}/ctype?${qs.stringify({ id: hash })}`);
  if (res.status !== 200) {
    throw new Error(`ctype query failed ${hash}`);
  }
  const ctype: CType = res.data.data.rawData;
  return ctype;
}
```

In this step, `ctypeHash` will be used as the query parameter of the HTTP GET request to get the ctype object.

4. Build the `Raw` object. In this step, we build a Raw object which is used for the subsequent construction of the RawCredential. The following explains each property of the Raw object:
   1. **contents**: The body of the credential;
   2. **owner**: holder/claimer, credential receiver;
   3. **ctype**: The ctype object used for this credential;
   4. **hashType**: Encryption algorithm type, here choose Keccak256 (we also support Blake2, Blake3, RescuePrimeOptimized and other encryption algorithms. Note: Considering that Keccak256 has the highest hash efficiency on chain, it is recommended to use Keccak256 as the hash when building Raw if your vc usage scenario does not include zk computation, otherwise use RescuePrimeOptimized hash).

```typescript
const raw = new Raw({
  contents: {
    id: 9870456,
    name: "vss-holder",
  },
  owner: holderDidUrl,
  ctype: ctype,
  hashType: "Keccak256",
});
```

5. Build the `RawCredential` object. In this step, we call `toRawCredential` API to generate RawCredential object based on the Raw object generated in the previous step. The encryption algorithm used in this step is Keccak256 by default (meanwhile, we also support other encryption algorithms, which are the same as the ones available for building Raw);

```typescript
const rawCredential: RawCredential = raw.toRawCredential("Keccak256");
```

6. Build the `vcBuilder` object. In this step, we build a vcBuilder object from which subsequent VCs can be built. vcBuilder provides several methods. For general purpose VCs, it is usually set to never expire and the issue time is set to the current time;

```typescript
const vcBuilder = VerifiableCredentialBuilder.fromRawCredential(
    rawCredential,
    ctype
  )
    .setExpirationDate(null)
    .setIssuanceDate(Date.now());
```

7. Build the `VC` object. In this step, you will use the `build` API in vcBuilder to build the VC. The two parameters of this API are described below:
   1. **issuer**: issuer's DID object;
   2. **isPublic**: true/false, when this parameter is false, the generated VC is private VC. If it is true, then public VC is generated.

```typescript
const vc: VerifiableCredential<false> = await vcBuilder.build(
  attester,
  false
);
```

8. Constructing encrypted messages using VC as message data. We will use the `encryptMessage` API to generate encrypted messages with the API parameters:
   1. **type**: Message type, corresponding to the VC's issue mode, is "Send\_issuedVC";
   2. **data**: Message data, here is VC;
   3. **sender**: Message sender's DID object, here is VC issuer;
   4. **receiverUrl**: Message receiver's keyAgreement DID URL;
   5. **reply**: Prefixed message id, this parameter is only used for responding to message scenarios;
   6. **resolver**: DID resolver.

```typescript
const message = await encryptMessage(
    "Send_issuedVC",
    vc,
    attester,
    holder.getKeyUrl("keyAgreement"),
    undefined,
    resolver
  );
```

9. Send the encrypted message to the server. This process initiates an HTTP POST request.

```typescript
await sendMessage2Server(message);

// src/utils/messageHelper.ts
export async function sendMessage2Server(
  message: any,
  templateId = -1,
  token = null,
  url = process.env.BASE_URL
): Promise<void> {
  const sendRes = await axios.post(`${url}/message`, {
    templateId,
    msg: message,
    token,
  });
  if (sendRes.status === 200) {
    console.log(`SUCCESS: send encrypted message to server`);
  } else {
    console.log(`send encrypted message response status: ${sendRes.status}`);
  }
}
```

Well, by following the 9 steps above, you will learn how to utilize the Issue mode of VC to issue a VC directly to the target user.


---

# 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.zcloak.network/developer-hub/guides/vc-operation/issue.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.
