Attestation Creation

Great! We now have a schema ready for use. We will refer to this schema throughout the remainder of the project by its ID, so save the ID of the schema you created. If you bypassed the previous step, you can use this schema to continue through this tutorial (Schema ID: onchain_evm_84532_0x34). Note that the on-chain ID of the schema is 0x34 and we will use this when creating an attestation.

Creating an Attestation

You can create an attestation using either our NPM SDK or by directly interacting with the respective Smart Contract for the specific network you are using.

Smart Contract Interaction

NOTE: If you selected a data storage option that is not directly on-chain (such as Arweave/IPFS), your schema will require Hybrid Attestations. Our SDK will handle this for you, but if you are interacting directly with Sign Protocol smart contracts, ensure that you are passing in an encoded Content ID (CID) as data when creating a hybrid attestation.

Let's write a function that takes in a contract's message string and the address of the person who signed it. You can get the Contract Address in the Address Book and the latest ABI on Etherscan.

import { Web3Provider } from "@ethersproject/providers";
import { BigNumber, Contract, ethers } from "ethers";

function createNotaryAttestation(contractDetails: string, signer: string) {
  let address = "0x..."; // Alice's address. Will need Alice's account to send the tx.
  let schemaData = ethers.utils.defaultAbiCoder.encode(
    ["string", "address"],
    [contractDetails, signer]
  // Standard setup for the contract
  const provider = new ethers.providers.JsonRpcProvider(
    // Get an RPC URL (such as an infura link) to connect to the network
  // Get the contract address from the Address Book in
  const contract = new Contract(CONTRACT_ADDRESS(84532), ISPABI.abi, provider);
  // Get the provider from the currently connected wallet
  const library = new Web3Provider(await connector.getProvider());
  // Create writable contract instance
  const instance = contract.connect(library.getSigner() as any) as Contract;
  // Send the attestation transaction
  try {
    await instance[
        schemaId: BigNumber.from("0x34"), // The final number from our schema's ID.
        linkedAttestationId: 0, // We are not linking an attestation.
        attestTimestamp: 0, // Will be generated for us.
        revokeTimestamp: 0, // Attestation is not revoked.
        attester: address, // Alice's address.
        validUntil: 0, // We are not setting an expiry date.
        dataLocation: 0, // We are placing data on-chain.
        revoked: false, // The attestation is not revoked.
        recipients: [signer], // Bob is our recipient.
        data: schemaData // The encoded schema data.
      signer.toLowerCase(), // Bob's lowercase address will be our indexing key.
      "0x", // No delegate signature.
      "0x00" // No extra data.
        async (tx: any) =>
          await tx.wait(1).then((res) => {
            console.log("success", res);
            // You can find the attestation's ID using the following path:
      .catch((err: any) => {
        console.log(err?.message ? err.message : err);
  } catch (err: any) {
    console.log(err?.message ? err.message : err);


The SDK simplifies the process rather than directly interacting with the smart contract. To perform the same action as above, we will do the following:

function createNotaryAttestation(contractDetails: string, signer: string) {
  const res = await client.createAttestation({
    schemaId: "0x34",
    data: {
    indexingValue: signer.toLowerCase()

Note that we can pass in all the attestation information like we did when sending the transaction directly to the smart contract, but we do not need to. The SDK will fill in the blank fields with their respective defaults. createAttestation will return data in the following format:

  attestationId: '0x..',
  txHash: '0x..',
  indexingValue: '...'

Now that you have successfully created an attestation, you need to be able to use it! When you're ready, move on to the next page.

Last updated