# attest

In the previous post, we, as Claimer, made a request to Attester to issue a VC. This time we will be responding to the previous request as Attester, so are you ready, Attesters? Let's get going.

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

## Tutorial

1. Initialize @noble cryptographic library and wasm;

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

2. Get attester's DID object from mnemonic;

```typescript
const mnemonic = process.env.ATTESTER_MNEMONIC as string;
const keyring = new Keyring();
const attester = keys.fromMnemonic(keyring, mnemonic, "ecdsa");
```

The method used to recover a DID object from a mnemonic is `fromMnemonic`, which takes two mandatory arguments, a keyring object and a string mnemonic, where the keyring object is used to manage the keypair;

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

3. Get the latest message from the server with receiver is attester and message type is Request\_Attestation;

```typescript
// get latest message
const serverMsg = await getMessage(attester, "Request_Attestation");

// src/utils/messageHelper.ts
export async function getMessage(
  receiver: Did,
  msgType: string,
  page = 1,
  size = 1,
  url = process.env.BASE_URL
) {
  const param = qs.stringify({
    page,
    size,
    receiver: receiver.getKeyUrl("keyAgreement"),
    msgType: msgType,
  });
  const res = await axios.get(`${url}/message/page?${param}`);

  return res.data.data.items.map((value: any) => value.rawData) as Array<
    Message<MessageType>
  >;
}
```

4. The attester decrypts the encrypted message obtained from the previous step and gets the RawCredential object wrapped by the claimer;

```typescript
// decrypt claim message
const decrypted = await decryptMessage(serverMsg[0], attester);

// get rawCredential from decrypt return value
const rawCredential: RawCredential = decrypted.data;
```

5. Get the ctype object via ctypeHash in RawCredential;

```typescript
const ctype = await getCtypeFromHash(rawCredential.ctype);

// 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;
}
```

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;&#x20;
   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. If the claim request is approved, the VC is used as the message data to construct the encrypted message, and the corresponding message type is "Response\_Approve\_Attestation", and if the request is rejected, the "data" field is set to empty and the message type is set to "Response\_Reject\_Attestation". When constructing the encrypted message, we will use the `encryptMessage` interface to generate the encrypted message with the following interface parameters:
   1. **type**: Message type, approval to issue VC corresponds to message type "Response\_Approve\_Attestation";
   2. **data**: Message data, here is VC;
   3. **sender**: Message sender's DID object, here is Attester;
   4. **receiverUrl**: Message receiver's keyAgreement DID URL;
   5. **reply**: Prefixed message id, this parameter is only used for responding to message scenarios, here is decrypted message id;
   6. **resolver**: DID resolver.

```typescript
const message = await encryptMessage(
  "Response_Approve_Attestation",
  vc,
  attester,
  decrypted.sender,
  decrypted.id
);
```

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, with the introduction of this tutorial, we have learned how to respond to a claimer's request from the Attester's perspective. For general VC usage scenarios, a trusted Attester will suffice, but for decentralized and high-trust scenarios, we'll need to see how multiple Attenders can work together to endorse a VC. In the next tutorial, you will learn how to make multiple endorsements to a VC.


---

# 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/claim-attest/attest.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.
