Step-by-step Guide

Setup

  1. Install zPass-SDK using npm install zpass-sdk.

  2. As zPass-SDK is using wasm for core functionality, install wasm supporting packages such as vite-plugin-wasm to make sure wasm can be run properly.

  3. Create a worker directory in your project.

  4. Create an AleoWorker.js file, import createAleoWorker() helper function to help initialize and manage workers.

  5. The createAleoWorker() takes an argument of an object with 2 values which are URL and optional baseURL, the url here is referring to the location of worker.js file that we are going to define our zPass functions in later. For example, if the worker.js is located at the same location as the AleoWorker.js file, the arguments of createAleoWorker() will be {“worker.js”, import.meta.url}. The import.meta.url will return the absolute URL of the current module regardless of how the application is deployed or served.

import { createAleoWorker } from "zpass-sdk";
const AleoWorker = () => {
    return createAleoWorker({
        url: "worker.js",
        baseUrl: import.meta.url,
    });
};
export { AleoWorker };
  1. Move on to create a new worker.js file to build zPass functions in worker using zPass-SDK.

  2. In worker.js file, import and call initThreadPool() to initialize a thread pool of Workers. This enables multi-threading, which significantly improves performance.

  3. Then proceed to create own zPass functions using zPass-SDK, these functions will be later exposed to the main threat using expose() from comlink. The expose() method takes an argument of an object with all the functions defined in workers.js.

Using zPass

  1. (Optional) Import initThreadPool to initialize a thread pool of workers to enable multi-threading and improve performance.

  2. Import ZPassSDK into worker.js, initialize ZPassSDK with user privateKey and optional host url to connect to the rpc node of Aleo network.

const sdk = new ZPassSDK({
    privateKey: privateKey,
    host: host
});
  1. Import expose from comlink to expose functions that are created in worker.js later.

  2. To start using zPass on-chain, a zPass program must be deployed onto the network or use any zPass program that has been deployed. Check out this guide on how to write a zPass program to prove certain credentials requirements.

  3. Once a zPass program is deployed on-chain, the first thing to do is to get the issuer to sign the credentials defined in the zPass program so that the users can issue themselves an on-chain zPass later.

  4. For example, first create a function called testZPass() and in the scope of it, let’s use the signCredential method from ZPassSDK.

  5. The signCredential method takes an argument as an object with fields:

    1. data: A credential object with properties and respective values same as defined in the deployed zPass program. Note that the name of each property must match the name of the field in the credential struct from the zPass program. The value must be in string type and appended with Aleo type suffix such as u32 in order to be able to parse correctly.

    2. hashType: Pick supported hash algorithm to use for hashing the data, type HashAlgorithm can be imported from zpass-sdk.

    3. privateKey?: An optional private key to switch using if the issuer account private key is not used during initialization of ZPassSDK.

  6. signCredential will return an object that contains signature and hash in string type, signature will be required as one of the inputs later during proveOffChain, proveOnChain or issueZPass.

const { signature } = await sdk.signCredential({
    data: {
      issuer: "aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px",
      subject: "aleo172s23z4lw3z3ruwc92dgukq8s0v3249jg28zsldq6a0adpw7c5gqfnkla2",
      dob: "19990301u32",
      nationality: "2148979field",
      expiry: "20250301u32",
      salt: "231scalar"
    },
    hashType: HashAlgorithm.POSEIDON2
  }); 
  1. After that, we can use the issueZPass method from ZPassSDK. Remember to initialize ZPassSDK before using its method.

  2. The issueZPass method takes an argument as an object with fields:

    1. programName: The name of the program to call in string type, which is the name of a zPass program that has been deployed on-chain with the suffix of .aleo.

    2. functionName: The name of the calling function in string type.

    3. privateFee: To spend fee from private records or not, either true or false.

    4. inputs: An array of strings which are the inputs to the program function.

    5. fee: Fee to spend in microcredit, in number type.

    6. feeRecord?: Optional fee records to pass for program execution if privateFee is true.

  3. The issueZPass method will return transactionId once successfully.

  4. In our example, by following the parameters of issue transition in verify_poseidon2_zpass.aleo program this will be:

const txId = await sdk.issueZPass({
    programName: "verify_poseidon2_zpass.aleo",
    functionName: "issue",
    privateFee: false,
    inputs: [
      signature,
      `{
        issuer: aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px,
        subject: aleo172s23z4lw3z3ruwc92dgukq8s0v3249jg28zsldq6a0adpw7c5gqfnkla2,
        dob: 19990301u32,
        nationality: 2148979field,
        expiry: 20250301u32
      }`,
      `{
        salt: 231scalar
      }`
    ],
    fee: 3000,
}); 
  1. Then return the txId back to the main application.

  2. To expose the testZPass function that we just created, use expose from comlink to expose it as a worker method like expose({ testZPass }); .

Test running ZPass worker method

  1. To try to run the testZpass() worker method that we just created, simply import AleoWorker() from AleoWorker.js, create an instant using AleoWorker() then call testZPass() method from that instant.

  2. To test it in the local development network, check out how to set it up here.

import { AleoWorker } from "./workers/AleoWorker.js";

const aleoWorker = AleoWorker();

const result = await aleoWorker.testZPass({
      privateKey: privateKey,
      host: hosturl
})

Last updated