# Solana

### How to generate the proof with Solana?

<pre class="language-javascript"><code class="lang-javascript">const generate = async (schemaId: string, appid: string) => {
    try {
      //check if you install the Phatom wallet
      if (!("phantom" in window)) {
        return alert("Please install Phantom wallet")
      }
      
      const provider = window.phantom?.solana
      const <a data-footnote-ref href="#user-content-fn-1">resp</a> = await provider?.connect() //connect wallet
      const account = resp.publicKey.toString()

      //The appid of the project created in dev center     
      const appid = "39a00e9e-7e6d-461e-9b9d-d520b355d1c0"
      //The schemaId of the project
      const schemaId = "c7eab8b7d7e44b05b41b613fe548edf5"
            
      const connector = new TransgateConnect(appid)
      
      const isAvailable = await connector.isTransgateAvailable()
      if (!isAvailable) {
        return alert("Please install zkPass TransGate")
      }
      
      const res = (await connector.launchWithSolana(schemaId, account)) as Result

    } catch (err) {
      alert(JSON.stringify(err))
      console.log("error", err)
    }
  }
</code></pre>

{% hint style="info" %}
The result includes two signatures: the allocator signature and the validator signature. Developers should verify both signatures based on the other returned fields.&#x20;
{% endhint %}

### Verify Allocator Signature

#### Encode the allocator message struct

```javascript

import { Buffer } from "buffer"
import secp256k1 from "secp256k1"
import * as borsh from "borsh"
import sha3 from 'js-sha3'

//Attest struct for Solana
const SolanaTask = {
  struct: {
    task: 'string',
    schema: 'string',
    notary: 'string',
  },
}

const { taskId, allocatorSignature, validatorAddress } = res //return by Transgate

const sig_bytes = hexToBytes(allocatorSignature.slice(2));

const signatureBytes = sig_bytes.slice(0, 64);
const recoverId = Array.from(sig_bytes.slice(64))[0];

const plaintext = borsh.serialize(SolanaTask, {
    task: taskId,
    schema: schema,
    notary: validatorAddress,
 });

const plaintextHash = Buffer.from(sha3.keccak_256.digest(Buffer.from(plaintext)));

```

#### Recover the allocator address

```javascript
const signedAllocatorAddress = secp256k1.ecdsaRecover(signatureBytes, recoverId, plaintextHash, false);
```

#### Check if the signed allocator address is registered. The current  allocator address is fixed.

```javascript
return signedAllocatorAddress === "69e7d686e612ab57e3619f4a19a567b3b212a5b35ba0e3b600fbed5c2ee9083d"
```

### Verify Validator Signature

#### Generate the validator message

```javascript
import { Buffer } from "buffer"
import secp256k1 from "secp256k1"
import * as borsh from "borsh"
import sha3 from "js-sha3"

//Attest struct for Solana
const Attest = {
  struct: {
    task: "string",
    schema: "string",
    nullifier: "string",
    recipient: "string",
    publicFieldsHash: "string",
  },
}

const { taskId, uHash, validatorAddress, schema, validatorSignature, recipient, publicFieldsHash } = res //return by Transgate
const sig_bytes = hexToBytes(validatorSignature.slice(2)) //skip the 0x

const signatureBytes = sig_bytes.slice(0, 64)
const recoverId = Array.from(sig_bytes.slice(64))[0]

const plaintext = borsh.serialize(Attest, {
  task: taskId,
  nullifier: uHash,
  schema,
  recipient,
  publicFieldsHash,
})

const plaintextHash = Buffer.from(sha3.keccak_256.digest(Buffer.from(plaintext)))
```

#### Recover the validator address

```javascript
 const signedValidatorAddress = secp256k1.ecdsaRecover(signatureBytes, recoverId, plaintextHash, false);
```

#### Verify if the signed validator address matches the address assigned by the allocator

```javascript
return signedValidatorAddress === validatorAddress
```

{% hint style="info" %}
Here, we've only given the reference code for js verification. However, the result can also be verified on Solana.
{% endhint %}

[^1]:
