Developer Guides

Setting up and docking a DP service

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.

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:

Parameter
Definition

schemaId

The schema ID of the content to verify

recipient

Ethereum address, indicating ownership of the proof

proxyFirst

Whether to use proxy mode; optional; defaults to true

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:

Parameter
Definition
Example

pageUrl

The page that needs to be opened for verification

apiUrl

The API endpoint that needs to be used for verification

responseMatches

Conditions that need to be met in the API response

""balance":\s*"(?.+?)""

responseRedactions

Fields that need to be exposed in the API response

"$.data.balance"

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.

schema_id
schema_name
schema_description

0x11cfba7609b799ef88da1e2a98b1f204cd966084c9877449f0d0ba72777c1559

binance register

Binance Account Ownership

0xc3c0ba7388eaa69bde72ce5eb12034b822b94c6778b67844df44c09ccd7e107c

okex register

OKX Account Ownership

0x8f21116770efb7978bb1c4e944da0141e48eab6ef02ca565abc96f75fb59da14

binance_kyc

Binance KYC Status

0xf2b160647a2c6fe42b5b80bb557538f3dddbfd494f89e9a5fe14acce1f8172ab

okex_kyc

OKX KYC Status

0x84705b16778a6166365b14f01cdbb3bdfac27a514c7ba7941e092dcafaf595ba

bybit_register

Bybit Account Ownership

0x86052f3dd2a49b58bba8fdb7ae3d811b1041ba904c7321b9c5d861bce6577743

bybit_kyc KYC

Bybit KYC Status

0xe16b1529bba7c77df2623408533b2708ee93ce03df41be4b14bfdca36a79aabc

gate_register

Gate Account Ownership

0x98fff7fe5fa719ed76f9524dc1c1406e1a17d664f124dcef5f45c188620f3678

gate_kyc

Gate KYC Status

0x8f9587fcce9bec6eae226eb8a92b68b79e2923b30453a1c4f50032691a6d847c

binance_balance_0

Binance Account balance > $0

0xed477f90ff03a79e539817028a5f417c19b3213da8e956d3f64f157a91f53610

bybit_balance_0

Bybit Account balance > $0

0x5d5cf2e2f64015ff992dfb381fb19090feaf5b064993b55abd2858b97647db6f

gate_balance_0

Gate Account balance > $0

0x4c0601d2c9fff3c7a7bbadd649c3e2b26c8ffc6ea99e11da4d3b7cf65974c31c

okex_balance_0

OKX Account balance > $0

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:

Parameter
Function

schema_id

The schema ID of the content to verify, e.g., Binance balance greater than 10 USDT

verifier_signature

The signature of the result, indicating that it passed the Orange Pass verification

recipient

Ethereum address, indicating ownership of the proof, preventing others from using the proof

user_hash

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

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>",
}
  1. 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>",
    }
}
  1. 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>",
}
  1. 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.

the parameter format should be:

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

Last updated

Was this helpful?