# Developer Guides

Integrating the Orange Pass typically only requires calling the browser extension, verifying, and saving the attestation data returned by the extension.

## Frontend

### Main Steps

To perform verification with Orange Pass, follow these steps:

1. Install the Orange Pass Chrome extension.
2. Call the methods provided by the Orange Pass extension to initiate proof.
3. Orange Pass opens the corresponding third-party page and executes the proof process.
4. The extension obtains the proof result and returns it to the page.
5. The page sends the proof result to its backend, which verifies whether the relevant data in the proof meets the requirements and updates the relevant status.
6. The frontend updates the frontend page based on the status updated by the backend.

#### Installing the Orange Pass Chrome Extension

To perform verification, users must first ensure that the extension is installed. You can determine whether the extension is installed by checking if the `window.orangePass` object is injected into the page. If the extension is not installed, guide the user to install it.&#x20;

#### Calling Methods Provided by the Orange Pass Extension to Initiate Verification

The injected `window.orangePass` object contains methods to initiate verification. The relevant type definitions are as follows:

```
// Verification result
interface VerifyResult {
  recipient: string;
  verifier_address: string;
  verifier_signature: string;
  data_hash: string;
  schema_id: string;
  task_id: string;
  user_hash: string;
}

// window.orangePass type definition 
interface OrangePass {
  start: (schemaId: string, recipient: string, proxyFirst?: boolean) => Promise<VerifyResult>;
}
```

The parameter definitions for the start method are as follows:

<table><thead><tr><th width="140.63671875">Parameter</th><th>Definition</th></tr></thead><tbody><tr><td>schemaId</td><td>The schema ID of the content to verify</td></tr><tr><td>recipient</td><td>Ethereum address, indicating ownership of the proof</td></tr><tr><td>proxyFirst</td><td>Whether to use proxy mode; optional; defaults to true</td></tr></tbody></table>

The specific usage is as follows

```
const startOrangePass = async () => {
  if (!window.orangePass) {
    // If the extension is not installed, guide to install it
    return;
  }

  // Execute proof and obtain the proof result
  const result = await window.orangePass.start(
    '***',
    '0x***',
    true,
  );
}
```

#### Orange Pass Opens the Corresponding Third-Party Page to Execute the Proof Process

When the `window.orangePass.start` method is called, the proof request is sent to the Orange Pass extension. The extension will use the provided `schemaId` parameter to retrieve the specific schema configuration, which records all the data required for the proof.

The core configuration parameters of the schema are as follows:

<table><thead><tr><th width="198.45703125">Parameter</th><th>Definition</th><th width="258.52734375">Example</th></tr></thead><tbody><tr><td>pageUrl</td><td>The page that needs to be opened for verification</td><td><a href="https://www.binance.com/">https://www.binance.com/</a></td></tr><tr><td>apiUrl</td><td>The API endpoint that needs to be used for verification</td><td><a href="https://www.binance.com/bapi/balance">https://www.binance.com/bapi/balance</a></td></tr><tr><td>responseMatches</td><td>Conditions that need to be met in the API response</td><td>""balance":\s*"(?.+?)""</td></tr><tr><td>responseRedactions</td><td>Fields that need to be exposed in the API response</td><td>"$.data.balance"</td></tr></tbody></table>

The core process is as follows

1. Retrieve the corresponding schema configuration using the schemaId, obtaining data such as pageUrl and apiUrl.
2. Open the third-party page at pageUrl.
3. Listen for requests to the apiUrl endpoint, using zero-knowledge proof technology to prove that the data returned by the apiUrl endpoint meets the requirements.
4. After verifying that the data returned by the apiUrl endpoint meets the requirements (e.g., Binance balance greater than 10 USDT), generate the proof.

#### How to obtain the schemaId?

Check all verifiable items on the Orange Pass official website and copy their schemaId. The Orange Pass official website is still under development.

<table><thead><tr><th width="421.734375">schema_id</th><th>schema_name</th><th>schema_description</th></tr></thead><tbody><tr><td>0x11cfba7609b799ef88da1e2a98b1f204cd966084c9877449f0d0ba72777c1559</td><td>binance register</td><td>Binance Account Ownership</td></tr><tr><td>0xc3c0ba7388eaa69bde72ce5eb12034b822b94c6778b67844df44c09ccd7e107c</td><td>okex register</td><td>OKX Account Ownership</td></tr><tr><td>0x8f21116770efb7978bb1c4e944da0141e48eab6ef02ca565abc96f75fb59da14</td><td>binance_kyc</td><td>Binance KYC Status</td></tr><tr><td>0xf2b160647a2c6fe42b5b80bb557538f3dddbfd494f89e9a5fe14acce1f8172ab</td><td>okex_kyc</td><td>OKX KYC Status</td></tr><tr><td>0x84705b16778a6166365b14f01cdbb3bdfac27a514c7ba7941e092dcafaf595ba</td><td>bybit_register</td><td>Bybit Account Ownership</td></tr><tr><td>0x86052f3dd2a49b58bba8fdb7ae3d811b1041ba904c7321b9c5d861bce6577743</td><td>bybit_kyc KYC</td><td>Bybit KYC Status</td></tr><tr><td>0xe16b1529bba7c77df2623408533b2708ee93ce03df41be4b14bfdca36a79aabc</td><td>gate_register</td><td>Gate Account Ownership</td></tr><tr><td>0x98fff7fe5fa719ed76f9524dc1c1406e1a17d664f124dcef5f45c188620f3678</td><td>gate_kyc</td><td>Gate KYC Status</td></tr><tr><td>0x8f9587fcce9bec6eae226eb8a92b68b79e2923b30453a1c4f50032691a6d847c</td><td>binance_balance_0</td><td>Binance Account balance > $0</td></tr><tr><td>0xed477f90ff03a79e539817028a5f417c19b3213da8e956d3f64f157a91f53610</td><td>bybit_balance_0</td><td>Bybit Account balance > $0</td></tr><tr><td>0x5d5cf2e2f64015ff992dfb381fb19090feaf5b064993b55abd2858b97647db6f</td><td>gate_balance_0</td><td>Gate Account balance > $0</td></tr><tr><td>0x4c0601d2c9fff3c7a7bbadd649c3e2b26c8ffc6ea99e11da4d3b7cf65974c31c</td><td>okex_balance_0</td><td>OKX Account balance > $0</td></tr><tr><td>0x21cfba7609b799ef88da1e2a98b1f204cd966084c9877449f0d0ba72777c1512</td><td>kucoin_kyc</td><td>KuCoin KYC Status</td></tr></tbody></table>

#### The Extension Obtains the Proof Result and Returns It to the Page

After obtaining the proof result, the extension will return the result to the page:

1. If the proof meets the requirements, the third-party verification page will automatically close, and the browser window will redirect to the page that initiated the verification.
2. If the proof does not meet the requirements or if there are other errors, the third-party verification page will not close automatically. It will display the error message on the third-party verification page while also throwing an error to the initiating verification page, which developers can catch and handle accordingly.

#### The Page Sends the Proof Result to Its Backend, Which Validates Whether the Proof Data Meets the Requirements and Updates the Relevant Status

Once a proof is successfully obtained, the page needs to send the proof to its backend, which will validate its validity (signature verification). For instructions on how the backend performs verification, refer to the relevant backend Markdown. The verification data sent to the backend is as follows:：

```
interface VerifyResult {
  recipient: string;
  verifier_address: string;
  verifier_signature: string;
  data_hash: string;
  schema_id: string;
  task_id: string;
  user_hash: string;
}
```

After the verification passes (signature verification), it can be proved that the user indeed meets the requirements corresponding to this schema\_id. The core relevant field descriptions are as follows:

<table><thead><tr><th width="202.5">Parameter</th><th>Function</th></tr></thead><tbody><tr><td>schema_id</td><td>The schema ID of the content to verify, e.g., Binance balance greater than 10 USDT</td></tr><tr><td>verifier_signature</td><td>The signature of the result, indicating that it passed the Orange Pass verification</td></tr><tr><td>recipient</td><td>Ethereum address, indicating ownership of the proof, preventing others from using the proof</td></tr><tr><td>user_hash</td><td>Hash value of the user ID who performed the verification in the third-party application; for instance, if verifying related to Binance, it would be the hash of the Binance ID to prevent generating the proof repeatedly with the same account</td></tr></tbody></table>

The logic following the proof verification is handled by the DApp-related backend itself. For example, after verifying the Binance balance greater than 10 USDT, the backend can change the relevant verification status to true.

#### The Frontend Updates Its Page Based on the Status Updated by the Backend

After sending the proof to the backend and receiving full verification, the frontend can request the latest data from the backend to update the frontend page. For instance, if the user's Binance balance is greater than 10 USDT, the UI should also be updated to reflect the status of the completed certification.

## Backend

The frontend will receive the Attestation data returned by Orange Notary, which can be submitted to the backend service requiring verification. The backend service is responsible for validating the Attestation's authenticity, ensuring that the signature address of the Attestation is the official address of Orange Notary's production environment.

### APIs

#### Notary (MPC Mode)

| Name                  | Path                   | Method |
| --------------------- | ---------------------- | ------ |
| Get Signing Address   | /notary/signingAddress | POST   |
| Generate Attestation  | /notary/genAttestation | POST   |
| Get Supported Schemas | /notary/schemas        | POST   |

1. **Get Signing Address**

Return the signing address for the notary

Path : /notary/signingAddress Method : POST Parameter :

Response :

```
{
    "code": "<signer address>",
}
```

2. **Generate Attestation**

Return the attestation based on schema data Path : /notary/genAttestation Method : POST Parameter :

```
{
    "schema_id": "<schema id for the attestation>",
    "data": "<encrypted data for the attestation>",
    "reciepint": "<recipient address for the attestation>",
}

```

Response :

```
{
    "data": {
        "recipient": "<reciepient address>",
        "verifier_address": "<verifier address for the attestation>",
        "verifier_signature": "<verifier signature for the attestation>",
        "data_hash": "<data hash for the attestation>",
        "schema_id": "<schema id for the attestation>",
        "task_id": "<task id , random and  unique  for each attestation>",
        "user_hash": "<user identifier hash for the attestation>",
    }
}

```

3. **Get Supported Schemas**

Return the supported schemas for the notary Path : /notary/schemas Method : POST Parameter :

```
{
    "conditions":{
        "wheres":[    // remove this if you want to return all schemas
            {
                "field_name":"schema_id",
                "field_op":"eq",
                "field_value":"<value>"
            }
        ],
        "orders":[
            {
                "field_name":"schema_id",
                "order":"desc"
            }
            ]
        }
    }
```

Response :

```
{
    "data":[
        {
           "ID":<seq no>,
           "SchemaName":"<name for the schema>",
           "NSchema":"<schema configuration>" ,
           "SchemaID":"<schema id>",
           "Category":"<category of the schema>",
           "Owner":"<owner of the schema>",
           "CreatedTime":"<created time>",
        }
    ]
}
```

#### Proxy (Proxy Mode)

| Name                 | Path                  | Method |
| -------------------- | --------------------- | ------ |
| Get Signing Address  | /proxy/signingAddress | POST   |
| Generate Attestation | /proxy/genAttestation | POST   |

1. **Get Signing Address**

Return the signing address for the notary

Path : /proxy/signingAddress Method : POST Parameter :

Response :

```
{
    "code": "<signer address>",
}
```

2. **Generate Attestation**

Return the attestation based on schema data Path : /proxy/genAttestation Method : POST Parameter :

```
{
    "schema_id": "<schema id for the attestation>",
    "data": "<encrypted data for the attestation>",
    "reciepint": "<recipient address for the attestation>",
}

```

Response :

```
{
    "data": {
        "recipient": "<reciepient address>",
        "verifier_address": "<verifier address for the attestation>",
        "verifier_signature": "<verifier signature for the attestation>",
        "data_hash": "<data hash for the attestation>",
        "schema_id": "<schema id for the attestation>",
        "task_id": "<task id , random and  unique  for each attestation>",
        "user_hash": "<user identifier hash for the attestation>",
    }
}
```

#### 1. Golang example

1. Calculate the hash of the attestation

```
type Attestation struct {
	Recipient       string `json:"recipient"`
	VerifierAddress string `json:"verifier_address"`
	DataHash        string `json:"data_hash"`
	SchemaID        string `json:"schema_id"`
	TaskID          string `json:"task_id"`
	UHash           string `json:"user_hash"`
}

func GetAttestationHash(attestation *Attestation) ([]byte, error) {
	taskBytes, err := hexutil.Decode(attestation.TaskID)
	if err != nil {
		return nil, err
	}
	uhashBytes, err := hexutil.Decode(attestation.UHash)
	if err != nil {
		return nil, err
	}
	siBytes, err := hexutil.Decode(attestation.SchemaID)
	if err != nil {
		return nil, err
	}
	dhBytes, err := hexutil.Decode(attestation.DataHash)
	if err != nil {
		return nil, err
	}

	atHash := crypto.Keccak256Hash(
		taskBytes,
		uhashBytes,
		siBytes,
		common.LeftPadBytes(common.HexToAddress(attestation.Recipient).Bytes(), 32),
		dhBytes,
		common.LeftPadBytes(common.HexToAddress(attestation.VerifierAddress).Bytes(), 32),
	).Bytes()

	return atHash, nil
}

//verify the signature for message
func ETHVerifyNotarySig(from, sigHex string, msg []byte) bool {
	fromAddr := ethcomm.HexToAddress(from)

	sig := hexutil.MustDecode(sigHex)
	if len(sig) < 64 {
		return false
	}
	// https://github.com/ethereum/go-ethereum/blob/55599ee95d4151a2502465e0afc7c47bd1acba77/internal/ethapi/api.go#L442
	if sig[64] != 27 && sig[64] != 28 {
		return false
	}
	sig[64] -= 27

	pubKey, err := crypto.SigToPub(msg, sig)
	if err != nil {
		return false
	}

	recoveredAddr := crypto.PubkeyToAddress(*pubKey)
	return strings.EqualFold(fromAddr.Hex(), recoveredAddr.Hex())
}
```

#### 2. Verify by smart contract

1. We also provide a smart contract for attestation verification. For Binance Smart Chain testnet, the contract address can be found in the [explorer](https://docs.ivymaker.io/user-guides/create-and-migrate).

<figure><img src="/files/GaReXNjHswOA6oA3hlP9" alt=""><figcaption></figcaption></figure>

the parameter format should be:

```
["<task_id>","<user_hash>","<schema_id>","<recipient>","<data_hash>","<verifier_address>","<verifier_signature>"]

```

<br>


---

# 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.orangeprotocol.io/developer-guides.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.
