Passport Issuer
  • INTRODUCTION
    • Intro to Quadrata Passport
    • Intro to Passport Issuers
  • INTEGRATION (DEVELOPERS)
    • Issuer Permission
    • Attesting attributes
      • 1. API Request
      • 2. API Response
      • 3. Minting Passport
    • Querying Attributes
    • Burning Passports
    • On-going Monitoring
  • Additional Information
    • Passport Attributes
    • Smart Contracts
    • Issuer Toolkit Library
Powered by GitBook
On this page
  1. INTEGRATION (DEVELOPERS)
  2. Attesting attributes

1. API Request

PreviousAttesting attributesNext2. API Response

Last updated 2 years ago

Quadrata is providing an for all DApps supporting Quadrata Passport technology. The npm package is responsible for collecting user information and sending those information to the issuers directly via an API call.

The overall API payload structure will differ from issuers to issuers as the data collected varies.

It is the responsibility of a passport issuers to have an API that includes at least the following fields:

Request Payload

{
    'account': '',
    'sigAccount': '',
    'chainId': ''

    // Remaining Issuer specific Request Payload
}
Field
Description

account

Wallet address of the user to verify

sigAccount

Ethereum ECDSA signature of a digest to prove ownership of the wallet account:

chainId

sigAccount

const { Signer, Wallet } = require("ethers");


export const signAccount = async (
  signer: typeof Signer
): Promise<typeof DataHexString> => {
  const DIGEST_TO_SIGN = "Welcome to Quadrata! By signing, you agree to the Terms of Service.";
  const sig = await signer.signMessage(DIGEST_TO_SIGN);
  return sig;
};

const signer = new Wallet(ACCOUNT_PRIVATE_KEY);

const account = signer.address;
const sigAccount = await signAccount(signer)
import codecs
import eth_abi
from web3 import Web3  # type: ignore

W3_TIMEOUT = 60
NETWORK_URI = "" # INFURA_RPC_NODE
ACCOUNT_PRIVATE_KEY = "" # PRIVATE_KEY_USED_TO_SIGN] 

def generate_mint_signature() -> Optional[str]:
    decoder = codecs.getdecoder('hex_codec')
    digest = "Welcome to Quadrata! By signing, you agree to the Terms of Service."

    decoder = codecs.getdecoder('hex_codec')
    w3 = Web3(Web3.HTTPProvider(NETWORK_URI, request_kwargs={'timeout': W3_TIMEOUT}))

    return w3.eth.account.sign_message(
        encode_defunct(hexstr=digest),
        private_key=decoder(str.encode(ACCOUNT_PRIVATE_KEY))[0],
    ).signature.hex()

It is the responsibility of the issuers to verify that the sigAccount matches the account.

Signature Verification

const { ethers } = require("ethers"); 

const verifyAccountSig = (account, sigAccount) => {
  const recoveredAddress = ethers.utils.recoverAddress(
    "Welcome to Quadrata! By signing, you agree to the Terms of Service.", 
    sigAccount
  );
  
  return recoveredAddress == account;
}
import eth_abi
from web3.auto import w3  # type: ignore
from eth_account.messages import encode_defunct

W3_TIMEOUT = 60


def is_verified_signature(
    signature: str, 
    expected_wallet_address: str
) -> bool:
    digest = "Welcome to Quadrata! By signing, you agree to the Terms of Service."
    try:
        encoded_msg = encode_defunct(text=digest)
        recovered_address = w3.eth.account.recover_message(
            encoded_msg, 
            signature=signature
        )
    except Exception:  # Intentionally broad as the errors thrown are not documented well
        return False

    return expected_wallet_address.lower() == recovered_address.lower()

Blockchain Network Id. (ex: 1 for Ethereum Mainnet, 137 for Polygon). See .

npm package
list of chain ID