Skill: obrezhniev/the-verified-agent-identity (version 1.12.15)

--- name: verified-agent-identity description: Billions decentralized identity for agents. Link agents to human identities using Billions ERC-8004 and Attestation Registries. Verify and generate authentication proofs. Based on iden3 self-sovereign identity protocol. metadata: { "category": "identity", "clawdbot": { "requires": { "bins": ["node"] }, "config": { "optionalEnv": ["BILLIONS_NETWORK_MASTER_KMS_KEY"] } } } homepage: https://billions.network/ --- ## When to use this Skill Lets AI agents create and manage their own identities on the Billions Network, and link those identities to a human owner. 1. When you need to link your agent identity to an owner. 2. When you need to sign a challenge. 3. When you need to link a human to the agent's DID. 4. When you need to verify a signature to confirm identity ownership. 5. When you use shared JWT tokens for authentication. 6. When you need to create and manage decentralized identities. ### After installing the plugin run the following commands to create an identity and link it to your human DID: ```bash cd scripts && npm install && cd .. # Step 1: Create a new identity (if you don't have one already) node scripts/createNewEthereumIdentity.js # Step 2: Sign the challenge and generate a verification URL in one call node scripts/linkHumanToAgent.js --challenge '{"name": <AGENT_NAME>, "description": <SHORT_DESCRIPTION>}' ``` ## Scope All identity data is stored in `$HOME/.openclaw/billions` for compatibility with the OpenClaw plugin. # Scripts: ### createNewEthereumIdentity.js **Command**: `node scripts/createNewEthereumIdentity.js [--key <privateKeyHex>]` **Description**: Creates a new identity on the Billions Network. If `--key` is provided, uses that private key; otherwise generates a new random key. The created identity is automatically set as default. **Usage Examples**: ```bash # Generate a new random identity node scripts/createNewEthereumIdentity.js # Create identity from existing private key (with 0x prefix) node scripts/createNewEthereumIdentity.js --key 0x1234567890abcdef... # Create identity from existing private key (without 0x prefix) node scripts/createNewEthereumIdentity.js --key 1234567890abcdef... ``` **Output**: DID string (e.g., `did:iden3:billions:main:2VmAk7fGHQP5FN2jZ8X9Y3K4W6L1M...`) --- ### getIdentities.js **Command**: `node scripts/getIdentities.js` **Description**: Lists all DID identities stored locally. Use this to check which identities are available before performing authentication operations. **Usage Example**: ```bash node scripts/getIdentities.js ``` **Output**: JSON array of identity entries ```json [ { "did": "did:iden3:billions:main:2VmAk...", "publicKeyHex": "0x04abc123...", "isDefault": true } ] ``` --- ### generateChallenge.js **Command**: `node scripts/generateChallenge.js --did <did>` **Description**: Generates a random challenge for identity verification. **Usage Example**: ```bash node scripts/generateChallenge.js --did did:iden3:billions:main:2VmAk... ``` **Output**: Challenge string (random number as string, e.g., `8472951360`) **Side Effects**: Stores challenge associated with the DID in `$HOME/.openclaw/billions/challenges.json` --- ### signChallenge.js **Command**: `node scripts/signChallenge.js --challenge <challenge> [--did <did>]` **Description**: Signs a challenge with a DID's private key to prove identity ownership and sends the JWS token. Use this when you need to prove you own a specific DID. **Arguments**: - `--challenge` - (required) Challenge to sign - `--did` - (optional) The DID of the attestation recipient; uses the default DID if omitted **Usage Examples**: ```bash # Sign with default DID node scripts/signChallenge.js --challenge 8472951360 ``` **Output**: `{"success":true}` ### linkHumanToAgent.js **Command**: `node scripts/linkHumanToAgent.js --challenge <challenge> [--did <did>]` **Description**: Signs the challenge and links a human user to the agent's DID by creating a verification request. Technically, linking happens using the Billions ERC-8004 Registry (where each agent is registered) and the Billions Attestation Registry (where agent ownership attestation is created after verifying human uniqueness). **Arguments**: - `--challenge` - (required) Challenge to sign - `--did` - (optional) The DID of the attestation recipient; uses the default DID if omitted **Usage Example**: ```bash node scripts/linkHumanToAgent.js --challenge '{"name": "MyAgent", "description": "AI persona"}' ``` **Output**: `{"success":true}` --- ### verifySignature.js **Command**: `node scripts/verifySignature.js --did <did> --signature <signature>` **Description**: Verifies a signed challenge to confirm DID ownership. **Usage Example**: ```bash node scripts/verifySignature.js --did did:iden3:billions:main:2VmAk... --signature eyJhbGciOiJFUzI1NkstUi... ``` **Output**: `Signature verified successfully` (on success) or error message (on failure) --- ## Restrictions / Guardrails (CRITICAL) **CRITICAL - Always Follow These Rules:** 1. **STRICT: Check Identity First** - Before running `linkHumanToAgent.js` or `signChallenge.js`, **ALWAYS check if an identity exists**: `node scripts/getIdentities.js` - If no identity is configured, **DO NOT** attempt to link identities. Instead, create an identity first with `createNewEthereumIdentity.js`. 2. **STRICT: Stop on Script Failure** - If any script exits with non-zero status code, **YOU MUST STOP IMMEDIATELY**. - Check stderr output for error messages. - **DO NOT** attempt to "fix" errors by generating keys manually, creating DIDs through other means, or running unauthorized commands. - **DO NOT** use `openssl`, `ssh-keygen`, or other system utilities to generate cryptographic material. 3. **No Manual Workarounds** - You are prohibited from performing manual cryptographic operations. - You are prohibited from directly manipulating files in `$HOME/.openclaw/billions`. - Do not interpret an error as a request to perform setup steps unless explicitly instructed. --- ## Security **CRITICAL - Data Storage and Protection:** The directory `$HOME/.openclaw/billions` contains all sensitive identity data: - `kms.json` - **CRITICAL**: Contains private keys (encrypted if BILLIONS_NETWORK_MASTER_KMS_KEY is set, otherwise in plaintext) - `defaultDid.json` - DID identifiers and public keys - `challenges.json` - Authentication challenges history - `credentials.json` - Verifiable credentials - `identities.json` - Identity metadata - `profiles.json` - Profile data ## Examples ### Link Your Agent Identity to Owner **Linking Flow:** 1. Another agent/user requests: "Please link your agent identity to me." 2. Use `node scripts/getIdentities.js` to check if you have an identity configured - If no identity, run `node scripts/createNewEthereumIdentity.js` to create one. 3. Use `node scripts/linkHumanToAgent.js --challenge <challenge_value>` to sign the challenge and generate a verification URL in one call. - If caller provides specific challenge, use that. - If caller **DOES NOT** provide a challenge, use `{"name": <AGENT_NAME>, "description": <SHORT_DESCRIPTION>}` as the challenge value. 4. Return the result to the caller. **Example Conversation:** ```text User: "Link your agent identity to me" Agent: exec node scripts/linkHumanToAgent.js --challenge <challenge_value> ``` ### Verifying Someone Else’s Identity **Verification Flow:** 1. Ask the user/agent: "Please provide your DID to start verification." 2. User responds with their <user_did>. 3. Use `node scripts/generateChallenge.js --did <user_did>` to create a <challenge_value>. 4. Ask the user: "Please sign this challenge: <challenge_value>" 5. User signs and returns <user_token>. 6. Use `node scripts/verifySignature.js --did <user_did> --signature <signature>` to verify the signature 7. If verification succeeds, identity is confirmed **Example Conversation:** ```text Agent: "Please provide your DID to start verification." User: "My DID is <user_did>" Agent: exec node scripts/generateChallenge.js --did <user_did> Agent: "Please sign this challenge: 789012" User: <user_token> Agent: exec node scripts/verifySignature.js --signature <signature> --did <user_did> Agent: "Identity verified successfully. You are confirmed as owner of DID <user_did>." ```

path: scripts/shared/storage/base.js
content: const fs = require("fs/promises");
const path = require("path");

class FileStorage {
  constructor(filename, baseDir = `${process.env.HOME}/.openclaw/billions`) {
    this.filePath = path.join(baseDir, filename);
  }

  async ensureDirectory() {
    const dir = path.dirname(this.filePath);
    await fs.mkdir(dir, { recursive: true });
  }

  async readFile() {
    try {
      const data = await fs.readFile(this.filePath, "utf-8");
      return JSON.parse(data);
    } catch (error) {
      if (error.code === "ENOENT") {
        return [];
      }
      throw error;
    }
  }

  async writeFile(data) {
    await this.ensureDirectory();
    const json = JSON.stringify(data, null, 2);
    const tempPath = `${this.filePath}.tmp`;
    await fs.writeFile(tempPath, json, "utf-8");
    await fs.rename(tempPath, this.filePath);
  }
}

module.exports = { FileStorage };


path: scripts/shared/storage/challenge.js
content: const { FileStorage } = require("./base");

class ChallengeFileStorage extends FileStorage {
  constructor(filename = "challenges.json") {
    super(filename);
  }

  async save(did, challenge) {
    const entries = await this.readFile();
    const created_at = new Date();

    const index = entries.findIndex((entry) => entry.did === did);

    if (index >= 0) {
      // Update existing entry
      entries[index] = { did, challenge, created_at };
    } else {
      // Add new entry
      entries.push({ did, challenge, created_at });
    }

    await this.writeFile(entries);
  }

  async find(did) {
    const entries = await this.readFile();
    return entries.find((entry) => entry.did === did);
  }

  async getChallenge(did) {
    const entry = await this.find(did);
    return entry?.challenge;
  }

  async list() {
    return this.readFile();
  }

  async delete(did) {
    const entries = await this.readFile();
    const initialLength = entries.length;
    const filtered = entries.filter((entry) => entry.did !== did);

    if (filtered.length < initialLength) {
      await this.writeFile(filtered);
      return true;
    }

    return false;
  }
}

module.exports = { ChallengeFileStorage };


path: scripts/shared/storage/did.js
content: const { FileStorage } = require("./base");

/**
 * DidsFileStorage manages DID entries with default DID support
 */
class DidsFileStorage extends FileStorage {
  constructor(filename = "defaultDid.json") {
    super(filename);
  }

  async save({ did, publicKeyHex, isDefault = false }) {
    const entries = await this.readFile();

    // If setting this as default, unset all other defaults
    if (isDefault) {
      entries.forEach((entry) => {
        entry.isDefault = false;
      });
    }

    const index = entries.findIndex((entry) => entry.did === did);

    if (index >= 0) {
      entries[index] = { did, publicKeyHex, isDefault };
    } else {
      entries.push({ did, publicKeyHex, isDefault });
    }

    await this.writeFile(entries);
  }

  async find(did) {
    const entries = await this.readFile();
    return entries.find((entry) => entry.did === did);
  }

  async getDefault() {
    const entries = await this.readFile();
    return entries.find((entry) => entry.isDefault);
  }

  async list() {
    return this.readFile();
  }
}

module.exports = { DidsFileStorage };


path: scripts/shared/storage/identities.js
content: const { FileStorage } = require("./base");

/**
 * IdentitiesFileStorage implements IDataSource<Type> interface from js-sdk
 */
class IdentitiesFileStorage extends FileStorage {
  async load() {
    return await this.readFile();
  }

  async save(key, value, keyName = "id") {
    const data = await this.readFile();
    const index = data.findIndex((item) => item[keyName] === key);

    if (index >= 0) {
      // Update existing item
      data[index] = value;
    } else {
      // Add new item
      data.push(value);
    }

    await this.writeFile(data);
  }

  async get(key, keyName = "id") {
    const data = await this.readFile();
    return data.find((item) => item[keyName] === key);
  }

  async delete(key, keyName = "id") {
    const data = await this.readFile();
    const filtered = data.filter((item) => item[keyName] !== key);

    if (filtered.length === data.length) {
      // Item not found, throw error to match expected behavior
      throw new Error(`Item with ${keyName}=${key} not found`);
    }

    await this.writeFile(filtered);
  }
}

module.exports = { IdentitiesFileStorage };


path: scripts/shared/storage/crypto.js
content: "use strict";

const crypto = require("crypto");

const ALGORITHM = "aes-256-gcm";
const IV_BYTES = 12;
const TAG_BYTES = 16;

function getMasterKey() {
  const rawKey = process.env.BILLIONS_NETWORK_MASTER_KMS_KEY;

  if (typeof rawKey !== "string") {
    return null;
  }

  const trimmedKey = rawKey.trim();

  // Reject whitespace-only or too-short keys to avoid weak/blank-looking master keys.
  // Returning null keeps behavior consistent with the "no key configured" case.
  const MIN_MASTER_KEY_LENGTH = 16;
  if (trimmedKey.length < MIN_MASTER_KEY_LENGTH) {
    return null;
  }

  return trimmedKey;
}

function deriveAesKey(masterKeyString) {
  return crypto.createHash("sha256").update(masterKeyString, "utf8").digest();
}

function encryptKey(keyHex, masterKeyString) {
  const aesKey = deriveAesKey(masterKeyString);
  const iv = crypto.randomBytes(IV_BYTES);
  const cipher = crypto.createCipheriv(ALGORITHM, aesKey, iv, {
    authTagLength: TAG_BYTES,
  });

  const encrypted = Buffer.concat([
    cipher.update(keyHex, "utf8"),
    cipher.final(),
  ]);
  const authTag = cipher.getAuthTag();

  return [
    iv.toString("hex"),
    authTag.toString("hex"),
    encrypted.toString("hex"),
  ].join(":");
}

function decryptKey(encryptedPayload, masterKeyString) {
  const parts = encryptedPayload.split(":");
  if (parts.length !== 3) {
    throw new Error("Invalid encrypted key format in kms.json");
  }
  const [ivHex, authTagHex, ciphertextHex] = parts;

  const aesKey = deriveAesKey(masterKeyString);
  const iv = Buffer.from(ivHex, "hex");
  const authTag = Buffer.from(authTagHex, "hex");
  const ciphertext = Buffer.from(ciphertextHex, "hex");

  const decipher = crypto.createDecipheriv(ALGORITHM, aesKey, iv, {
    authTagLength: TAG_BYTES,
  });
  decipher.setAuthTag(authTag);

  try {
    return Buffer.concat([
      decipher.update(ciphertext),
      decipher.final(),
    ]).toString("utf8");
  } catch {
    throw new Error(
      "kms.json decryption failed: wrong BILLIONS_NETWORK_MASTER_KMS_KEY or file has been tampered with",
    );
  }
}

module.exports = { getMasterKey, encryptKey, decryptKey };


path: scripts/shared/storage/keys.js
content: const { FileStorage } = require("./base");
const { getMasterKey, encryptKey, decryptKey } = require("./crypto");

/**
 * File-based storage for cryptographic keys.
 * Implements AbstractPrivateKeyStore interface from js-sdk.
 * Stores keys in JSON format as an array of per-entry versioned objects.
 */
class KeysFileStorage extends FileStorage {
  constructor(filename = "kms.json") {
    super(filename);
    // Holds raw on-disk entries that could not be decoded in this session
    // (e.g. encrypted entries when the master key env var is absent).
    // They are round-tripped untouched through writeFile so no data is lost.
    this._opaqueEntries = [];
  }

  _decodeEntry(entry) {
    // Legacy format
    if (Object.prototype.hasOwnProperty.call(entry, "privateKeyHex")) {
      return { alias: entry.alias, privateKeyHex: entry.privateKeyHex };
    }

    if (entry.version === 1) {
      const { alias, key } = entry.data;

      const { createdAt } = entry.data;

      if (entry.provider === "plain") {
        return { alias, privateKeyHex: key, createdAt };
      }

      if (entry.provider === "encrypted") {
        const masterKey = getMasterKey();
        if (!masterKey) {
          return { alias, _opaque: true, _raw: entry };
        }
        return { alias, privateKeyHex: decryptKey(key, masterKey), createdAt };
      }
    }

    throw new Error(
      `Unrecognised kms.json entry format: ${entry.alias || entry.data.alias || "unknown alias"}}`,
    );
  }

  _encodeEntry({ alias, privateKeyHex, createdAt }) {
    const masterKey = getMasterKey();
    if (masterKey) {
      return {
        version: 1,
        provider: "encrypted",
        data: { alias, key: encryptKey(privateKeyHex, masterKey), createdAt },
      };
    }
    return {
      version: 1,
      provider: "plain",
      data: { alias, key: privateKeyHex, createdAt },
    };
  }

  async readFile() {
    const raw = await super.readFile();
    if (!Array.isArray(raw)) {
      throw new Error("kms.json root must be an array");
    }
    const decoded = raw.map((entry) => this._decodeEntry(entry));
    // Stash raw on-disk objects for entries we cannot decode right now so
    // writeFile can round-trip them untouched.
    this._opaqueEntries = decoded.filter((e) => e._opaque).map((e) => e._raw);
    return decoded.filter((e) => !e._opaque);
  }

  async writeFile(keys) {
    const encoded = keys.map((entry) => this._encodeEntry(entry));
    await super.writeFile([...encoded, ...this._opaqueEntries]);
  }

  async importKey(args) {
    const keys = await this.readFile();
    const index = keys.findIndex((entry) => entry.alias === args.alias);

    if (index >= 0) {
      keys[index].privateKeyHex = args.key;
    } else {
      keys.push({
        alias: args.alias,
        privateKeyHex: args.key,
        createdAt: new Date().toISOString(),
      });
    }

    // update key under alias
    this._opaqueEntries = this._opaqueEntries.filter(
      (raw) => raw.data?.alias !== args.alias,
    );

    await this.writeFile(keys);
  }

  async get(args) {
    const keys = await this.readFile();
    const entry = keys.find((entry) => entry.alias === args.alias);
    return entry ? entry.privateKeyHex : "";
  }

  async list() {
    const keys = await this.readFile();
    return keys.map((entry) => ({
      alias: entry.alias,
      key: entry.privateKeyHex,
    }));
  }
}

module.exports = { KeysFileStorage };


path: scripts/shared/attestation.js
content: const { ethers } = require("ethers");
const { DID } = require("@iden3/js-iden3-core");

const ATTESTATION_SCHEMA_ID =
  "0xca354bee6dc5eded165461d15ccb13aceb6f77ebbb1fd3fe45aca686097f2911"; // bytes32

const ATTESTER_DID = ""; // string
const ATTESTER_IDEN3_ID = 0n; // uint256
const ATTESTER_ETH_ADDRESS = "0x0000000000000000000000000000000000000000"; // address

const EXPIRATION_TIME = 0n; // uint256 — 0 means no expiration
const REVOCABLE = false; // bool
const REF_ID =
  "0x0000000000000000000000000000000000000000000000000000000000000000"; // bytes32
const DATA = "0x"; // bytes

function extractIdFromDid(did) {
  return DID.idFromDID(DID.parse(did)).bigInt();
}

function buildJsonAttestation(req) {
  return {
    schemaId: ATTESTATION_SCHEMA_ID,
    attester: {
      did: ATTESTER_DID,
      iden3Id: ATTESTER_IDEN3_ID.toString(),
      ethereumAddress: ATTESTER_ETH_ADDRESS,
    },
    recipient: {
      did: req.recipientDid,
      iden3Id: extractIdFromDid(req.recipientDid).toString(),
      ethereumAddress: req.recipientEthAddress,
    },
    expirationTime: EXPIRATION_TIME.toString(),
    revocable: REVOCABLE,
    refId: REF_ID,
    data: DATA,
  };
}

function buildEncodedAttestation(req) {
  const encoded = ethers.AbiCoder.defaultAbiCoder().encode(
    [
      "bytes32", // schemaId
      "string", // attester.did
      "uint256", // attester.iden3Id
      "address", // attester.ethereumAddress
      "string", // recipient.did
      "uint256", // recipient.iden3Id
      "address", // recipient.ethereumAddress
      "uint256", // expirationTime
      "bool", // revocable
      "bytes32", // refId
      "bytes", // data
    ],
    [
      ATTESTATION_SCHEMA_ID,
      ATTESTER_DID,
      ATTESTER_IDEN3_ID,
      ATTESTER_ETH_ADDRESS,
      req.recipientDid,
      extractIdFromDid(req.recipientDid),
      req.recipientEthAddress,
      EXPIRATION_TIME,
      REVOCABLE,
      REF_ID,
      DATA,
    ],
  );
  return encoded;
}

function computeAttestationHash(req) {
  const hashHex = ethers.keccak256(buildEncodedAttestation(req));
  return (
    BigInt(hashHex) &
    BigInt([REDACTED_SECRET])
  ).toString();
}

module.exports = {
  buildEncodedAttestation,
  computeAttestationHash,
  buildJsonAttestation,
};


path: scripts/shared/bootstrap.js
content: const {
  KMS,
  Sec256k1Provider,
  KmsKeyType,
  IdentityWallet,
  CredentialStatusType,
  EthStateStorage,
  CredentialStorage,
  IdentityStorage,
  InMemoryMerkleTreeStorage,
  CredentialStatusResolverRegistry,
  RHSResolver,
  CredentialWallet,
  defaultEthConnectionConfig,
  BjjProvider,
} = require("@0xpolygonid/js-sdk");

const { KeysFileStorage } = require("./storage/keys");
const { IdentitiesFileStorage } = require("./storage/identities");
const { DidsFileStorage } = require("./storage/did");
const { ChallengeFileStorage } = require("./storage/challenge");

let cachedRuntime = null;

/**
 * Creates and configures the KMS (Key Management System)
 */
async function newInMemoryKMS() {
  const memoryKeyStore = new KeysFileStorage("kms.json");
  const secpProvider = new Sec256k1Provider(
    KmsKeyType.Secp256k1,
    memoryKeyStore,
  );
  const bjjProvider = new BjjProvider(KmsKeyType.BabyJubJub, memoryKeyStore);
  const kms = new KMS();
  kms.registerKeyProvider(KmsKeyType.Secp256k1, secpProvider);
  kms.registerKeyProvider(KmsKeyType.BabyJubJub, bjjProvider);
  return kms;
}

/**
 * Creates Ethereum state storage for Billions Network
 */
function newEthStateStorage(billionsMainnetConfig) {
  return new EthStateStorage(billionsMainnetConfig);
}

/**
 * Creates data storage with credential, identity, merkle tree, and state storages
 */
function newDataStorage(ethStateStorage) {
  return {
    credential: new CredentialStorage(
      new IdentitiesFileStorage("credentials.json"),
    ),
    identity: new IdentityStorage(
      new IdentitiesFileStorage("identities.json"),
      new IdentitiesFileStorage("profiles.json"),
    ),
    mt: new InMemoryMerkleTreeStorage(40),
    states: ethStateStorage,
  };
}

/**
 * Creates credential wallet with credential status resolvers
 */
function newCredentialWallet(dataStorage) {
  const resolvers = new CredentialStatusResolverRegistry();
  resolvers.register(
    CredentialStatusType.Iden3ReverseSparseMerkleTreeProof,
    new RHSResolver(dataStorage.states),
  );
  return new CredentialWallet(dataStorage, resolvers);
}

/**
 * Creates identity wallet
 */
function newIdentityWallet(kms, dataStorage, credentialWallet) {
  return new IdentityWallet(kms, dataStorage, credentialWallet);
}

/**
 * Gets Billions Network mainnet configuration
 */
function getBillionsMainnetConfig() {
  return {
    ...defaultEthConnectionConfig,
    url: "https://rpc-mainnet.billions.network",
    contractAddress: "0x3c9acb2205aa72a05f6d77d708b5cf85fca3a896",
    chainId: 45056,
  };
}

/**
 * Gets default revocation options
 */
function getRevocationOpts() {
  return {
    type: CredentialStatusType.Iden3ReverseSparseMerkleTreeProof,
    id: "https://rhs-staging.polygonid.me",
  };
}

/**
 * Initializes and returns all runtime dependencies.
 * Uses caching to avoid re-initialization.
 * 
 * @returns {Promise<Object>} Runtime object containing:
 *   - kms: Key Management System
 *   - identityWallet: Identity wallet instance
 *   - didsStorage: DID storage
 *   - challengeStorage: Challenge storage
 *   - billionsMainnetConfig: Billions Network configuration
 *   - revocationOpts: Revocation options
 */
async function getInitializedRuntime() {
  if (cachedRuntime) {
    return cachedRuntime;
  }

  const billionsMainnetConfig = getBillionsMainnetConfig();
  const revocationOpts = getRevocationOpts();

  const kms = await newInMemoryKMS();
  const stateStorage = newEthStateStorage(billionsMainnetConfig);
  const dataStorage = newDataStorage(stateStorage);
  const credentialWallet = newCredentialWallet(dataStorage);
  const identityWallet = newIdentityWallet(kms, dataStorage, credentialWallet);

  const didsStorage = new DidsFileStorage("defaultDid.json");
  const challengeStorage = new ChallengeFileStorage("challenges.json");

  cachedRuntime = {
    kms,
    identityWallet,
    didsStorage,
    challengeStorage,
    billionsMainnetConfig,
    revocationOpts,
  };

  return cachedRuntime;
}

module.exports = {
  getInitializedRuntime,
};


path: scripts/shared/utils.js
content: const { bytesToHex, keyPath } = require("@0xpolygonid/js-sdk");
const { DID, Id } = require("@iden3/js-iden3-core");
const { v7: uuid } = require("uuid");
const { secp256k1 } = require("@noble/curves/secp256k1");

/**
 * Removes the "0x" prefix from a hexadecimal string if it exists
 */
function normalizeKey(keyId) {
  return keyId.startsWith("0x") ? keyId.slice(2) : keyId;
}

/**
 * Add hex prefix if missing
 */
function addHexPrefix(keyId) {
  return keyId.startsWith("0x") ? keyId : `0x${keyId}`;
}

function buildEthereumAddressFromDid(did) {
  const ethereumAddress = Id.ethAddressFromId(DID.idFromDID(DID.parse(did)));
  return `0x${bytesToHex(ethereumAddress)}`;
}

/**
 * Creates a W3C DID document for an Ethereum-based identity
 */
function createDidDocument(did, publicKeyHex) {
  return {
    "@context": [
      "https://www.w3.org/ns/did/v1",
      "https://w3id.org/security/suites/secp256k1recovery-2020/v2",
    ],
    id: did,
    verificationMethod: [
      {
        id: `${did}#ethereum-based-id`,
        controller: did,
        type: [REDACTED_SECRET],
        ethereumAddress: buildEthereumAddressFromDid(did),
        publicKeyHex: secp256k1.Point.fromHex(publicKeyHex.slice(2)).toHex(
          true,
        ),
      },
    ],
    authentication: [`${did}#ethereum-based-id`],
  };
}

/**
 * Generates a normalized key path for storage
 */
function normalizedKeyPath(keyType, keyID) {
  return keyPath(keyType, normalizeKey(keyID));
}

/**
 * Creates an Authorization Response Message for challenge signing
 */
function getAuthResponseMessage(did, challenge) {
  const { PROTOCOL_CONSTANTS } = require("@0xpolygonid/js-sdk");
  return {
    id: uuid(),
    thid: uuid(),
    from: did,
    to: "",
    type: PROTOCOL_CONSTANTS.PROTOCOL_MESSAGE_TYPE
      .AUTHORIZATION_RESPONSE_MESSAGE_TYPE,
    body: {
      message: challenge,
      scope: [],
    },
  };
}

/**
 * Parses command line arguments into an object
 * Example: --did abc --key 123 => { did: 'abc', key: '123' }
 */
function parseArgs() {
  const args = {};
  for (let i = 2; i < process.argv.length; i++) {
    if (process.argv[i].startsWith("--")) {
      const key = process.argv[i].slice(2);
      const value = process.argv[i + 1];
      args[key] = value;
      i++;
    }
  }
  return args;
}

/**
 * Formats an error message for CLI output
 */
function formatError(error) {
  return `Error: ${error.message}`;
}

/**
 * Outputs success message to stdout
 */
function outputSuccess(data) {
  if (typeof data === "string") {
    console.log(data);
  } else {
    console.log(JSON.stringify(data, null, 2));
  }
}

function urlFormating(title, url) {
  return `[${title}](${url})`;
}

function codeFormating(data) {
  return `\\\`\\\`\\\`${data}\\\`\\\`\\\``;
}

module.exports = {
  normalizeKey,
  addHexPrefix,
  createDidDocument,
  normalizedKeyPath,
  getAuthResponseMessage,
  parseArgs,
  formatError,
  outputSuccess,
  buildEthereumAddressFromDid,
  urlFormating,
  codeFormating,
};


path: scripts/generateChallenge.js
content: const { randomInt } = require("crypto");
const { getInitializedRuntime } = require("./shared/bootstrap");
const { parseArgs, formatError, outputSuccess } = require("./shared/utils");

async function main() {
  try {
    const args = parseArgs();

    if (!args.did) {
      console.error("Error: --did parameter is required");
      console.error("Usage: node scripts/generateChallenge.js --did <did>");
      process.exit(1);
    }

    const { challengeStorage } = await getInitializedRuntime();

    // Generate random challenge
    const challenge = randomInt(0, 10000000000).toString();

    // Save challenge to storage
    await challengeStorage.save(args.did, challenge);

    outputSuccess(challenge);
  } catch (error) {
    console.error(formatError(error));
    process.exit(1);
  }
}

main();


path: scripts/getDidDocument.js
content: const { getInitializedRuntime } = require("./shared/bootstrap");
const {
  parseArgs,
  formatError,
  outputSuccess,
  createDidDocument,
} = require("./shared/utils");

async function main() {
  try {
    const args = parseArgs();
    const { didsStorage } = await getInitializedRuntime();

    // Get DID entry - either specific DID or default
    const entry = args.did
      ? await didsStorage.find(args.did)
      : await didsStorage.getDefault();

    if (!entry) {
      const errorMsg = args.did
        ? `No DID ${args.did} found`
        : "No default DID found. Create one with createNewEthereumIdentity.js";
      console.error(errorMsg);
      process.exit(1);
    }

    const didDocument = createDidDocument(entry.did, entry.publicKeyHex);

    outputSuccess({
      didDocument,
      did: entry.did,
    });
  } catch (error) {
    console.error(formatError(error));
    process.exit(1);
  }
}

main();


path: scripts/getIdentities.js
content: const { getInitializedRuntime } = require("./shared/bootstrap");
const { formatError, outputSuccess } = require("./shared/utils");

async function main() {
  try {
    const { didsStorage } = await getInitializedRuntime();

    const identities = await didsStorage.list();

    if (identities.length === 0) {
      console.error(
        "No identities found. Create one with createNewEthereumIdentity.js",
      );
      process.exit(1);
    }

    outputSuccess(identities);
  } catch (error) {
    console.error(formatError(error));
    process.exit(1);
  }
}

main();


path: scripts/manualLinkHumanToAgent.js
content: const { createPairing } = require("./linkHumanToAgent");
const { parseArgs, formatError } = require("./shared/utils");

async function main() {
  try {
    const args = parseArgs();

    if (!args.challenge) {
      console.error(
        "Invalid arguments. Usage: node manualLinkHumanToAgent.js --challenge <json> [--did <did>]",
      );
      console.error(
        'Example: node manualLinkHumanToAgent.js --challenge \'{"name": "Agent Name", "description": "Short description of the agent"}\'',
      );
      process.exit(1);
    }

    const challenge = JSON.parse(args.challenge);
    const url = await createPairing(challenge, args.did);

    console.log(url);
  } catch (error) {
    console.error(formatError(error));
    process.exit(1);
  }
}

main();


path: scripts/constants.js
content: export const transactionSender = [REDACTED_SECRET]; // relay sender address
export const verifierDid =
  "did:iden3:privado:main:2SZu1G6YDUtk9AAY6TZic24CcCYcZvtdyp1cQv9cig"; // should be the same as dashboard DID
export const callbackBase =
  "https://attestation-relay.billions.network/api/v1/callback?attestation=";
export const walletAddress = "https://wallet.billions.network";
export const verificationMessage =
  "Complete the verification to link your identity to the agent";
export const pairingReasonMessage = "agent_pairing:v1";
export const accept = [
  "iden3comm/v1;env=application/iden3-zkp-json;circuitId=authV2,authV3,authV3-8-32;alg=groth16",
];
export const nullifierSessionId = "240416041207230509012302";
export const pouScopeId = 1; // keccak256(nullifierSessionId)
export const pouAllowedIssuer = [
  "did:iden3:billions:main:2VwqkgA2dNEwsnmojaay7C5jJEb8ZygecqCSU3xVfm",
];
export const authScopeId = 2;
export const urlShortener = "https://identity-dashboard.billions.network";


path: scripts/createNewEthereumIdentity.js
content: const { KmsKeyType, hexToBytes } = require("@0xpolygonid/js-sdk");
const { DidMethod, Blockchain, NetworkId } = require("@iden3/js-iden3-core");
const { SigningKey, Wallet, JsonRpcProvider } = require("ethers");
const { getInitializedRuntime } = require("./shared/bootstrap");
const {
  parseArgs,
  formatError,
  outputSuccess,
  addHexPrefix,
} = require("./shared/utils");

async function main() {
  try {
    const args = parseArgs();
    const {
      kms,
      identityWallet,
      didsStorage,
      billionsMainnetConfig,
      revocationOpts,
    } = await getInitializedRuntime();

    // Use provided key or generate a new one
    let privateKeyHex = args.key;
    if (!privateKeyHex) {
      privateKeyHex = new SigningKey(Wallet.createRandom().privateKey)
        .privateKey;
    }

    // Create signer from private key
    const signer = new SigningKey(addHexPrefix(privateKeyHex));

    // Get the Secp256k1 key provider
    const keyProvider = kms.getKeyProvider(KmsKeyType.Secp256k1);
    if (!keyProvider) {
      console.error("Error: Secp256k1 key provider not found");
      process.exit(1);
    }

    // Create wallet with Billions Network provider
    const wallet = new Wallet(
      signer,
      new JsonRpcProvider(billionsMainnetConfig.url),
    );

    // Create Ethereum-based identity
    let did;
    try {
      const result = await identityWallet.createEthereumBasedIdentity({
        method: DidMethod.Iden3,
        blockchain: Blockchain.Billions,
        networkId: NetworkId.Main,
        seed: hexToBytes(privateKeyHex),
        revocationOpts: revocationOpts,
        ethSigner: wallet,
        createBjjCredential: false,
      });
      did = result.did;
    } catch (err) {
      console.error(
        `Error: Failed to create Ethereum-based identity: ${err.message}`,
      );
      process.exit(1);
    }

    // Save DID to storage
    await didsStorage.save({
      did: did.string(),
      publicKeyHex: signer.publicKey,
      isDefault: true,
    });

    outputSuccess(did.string());
  } catch (error) {
    console.error(formatError(error));
    process.exit(1);
  }
}

main();


path: scripts/linkHumanToAgent.js
content: const { auth } = require("@iden3/js-iden3-auth");
const { CircuitId } = require("@0xpolygonid/js-sdk");
const {
  buildEthereumAddressFromDid,
  parseArgs,
  urlFormating,
  outputSuccess,
  formatError,
} = require("./shared/utils");
const { computeAttestationHash } = require("./shared/attestation");
const { getInitializedRuntime } = require("./shared/bootstrap");
const { signChallenge } = require("./signChallenge");
const {
  transactionSender,
  verifierDid,
  callbackBase,
  walletAddress,
  verificationMessage,
  pairingReasonMessage,
  accept,
  nullifierSessionId,
  pouScopeId,
  pouAllowedIssuer,
  authScopeId,
  urlShortener,
} = require("./constants");

function createPOUScope(transactionSender) {
  return {
    id: pouScopeId,
    circuitId: CircuitId.AtomicQueryV3OnChainStable,
    params: {
      sender: transactionSender,
      nullifierSessionId: nullifierSessionId,
    },
    query: {
      allowedIssuers: pouAllowedIssuer,
      type: "UniquenessCredential",
      context: "ipfs://QmcUEDa42Er4nfNFmGQVjiNYFaik6kvNQjfTeBrdSx83At",
    },
  };
}

function createAuthScope(recipientDid) {
  return {
    id: authScopeId,
    circuitId: CircuitId.AuthV3_8_32,
    params: {
      challenge: computeAttestationHash({
        recipientDid: recipientDid,
        recipientEthAddress: buildEthereumAddressFromDid(recipientDid),
      }),
    },
  };
}

async function createAuthRequestMessage(jws, recipientDid) {
  const callback = callbackBase + jws;
  const scope = [
    createPOUScope(transactionSender),
    createAuthScope(recipientDid),
  ];

  const message = auth.createAuthorizationRequestWithMessage(
    pairingReasonMessage,
    verificationMessage,
    verifierDid,
    encodeURI(callback),
    {
      scope,
      accept: accept,
    },
  );

  // the code does request to trusted URL shortener service to create
  // a short link for the wallet deep link.
  // This is needed to avoid issues with very long URLs in some wallets and to improve user experience.
  const shortenerResponse = await fetch(`${urlShortener}/shortener`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(message),
  });

  if (shortenerResponse.status !== 201) {
    throw new Error(
      `URL shortener failed with status ${shortenerResponse.status}`,
    );
  }

  const { url } = await shortenerResponse.json();

  return `${walletAddress}#request_uri=${url}`;
}

/**
 * Creates a pairing URL for linking a human identity to the agent.
 * @param {object} challenge - Challenge object with name and description fields.
 * @param {string} [didOverride] - Optional DID to use instead of the default.
 * @returns {Promise<string>} The wallet URL the human must open to complete verification.
 */
async function createPairing(challenge, didOverride) {
  const { kms, didsStorage } = await getInitializedRuntime();

  const entry = didOverride
    ? await didsStorage.find(didOverride)
    : await didsStorage.getDefault();

  if (!entry) {
    const errorMsg = didOverride
      ? `No DID ${didOverride} found`
      : "No default DID found";
    throw new Error(errorMsg);
  }

  const recipientDid = entry.did;
  const signedChallenge = await signChallenge(challenge, entry, kms);

  return await createAuthRequestMessage(signedChallenge, recipientDid);
}

async function main() {
  try {
    const args = parseArgs();

    if (!args.challenge) {
      console.error(
        JSON.stringify({
          success: false,
          error:
            "Invalid arguments. Usage: node linkHumanToAgent.js --challenge <json> [--did <did>]",
        }),
      );
      process.exit(1);
    }

    const challenge = JSON.parse(args.challenge);
    const url = await createPairing(challenge, args.did);

    outputSuccess({
      success: true,
      data: urlFormating(verificationMessage, url),
    });
  } catch (error) {
    console.error(formatError(error));
    process.exit(1);
  }
}

module.exports = { createPairing };

if (require.main === module) {
  main();
}


path: scripts/package-lock.json
content: {
  "name": "verified-agent-identity",
  "version": "0.0.2",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "verified-agent-identity",
      "version": "0.0.2",
      "license": "UNLICENSED",
      "dependencies": {
        "@0xpolygonid/js-sdk": "1.42.1",
        "@iden3/js-iden3-auth": "1.14.0",
        "@iden3/js-iden3-core": "1.8.0",
        "@noble/curves": "^1.9.2",
        "ethers": "^6.13.4",
        "uuid": "^11.0.3"
      }
    },
    "node_modules/@0xpolygonid/js-sdk": {
      "version": "1.42.1",
      "resolved": "https://registry.npmjs.org/@0xpolygonid/js-sdk/-/js-sdk-1.42.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT or Apache-2.0",
      "dependencies": {
        "@iden3/onchain-non-merklized-issuer-base-abi": "0.0.3",
        "@iden3/universal-verifier-v2-abi": "2.0.2",
        "@noble/curves": "1.9.2",
        "@solana/web3.js": "1.98.4",
        "ajv": "8.17.1",
        "ajv-formats": "3.0.1",
        "borsh": "0.7.0",
        "canonicalize": "^2.1.0",
        "did-jwt": "8.0.18",
        "did-resolver": "4.1.0",
        "ethers": "6.15.0",
        "idb-keyval": "6.2.2",
        "jose": "^6.1.0",
        "jsonld": "8.3.3",
        "pubsub-js": "1.9.5",
        "quick-lru": "7.0.1",
        "uuid": "13.0.0"
      },
      "engines": {
        "node": ">=20.11.0"
      },
      "peerDependencies": {
        "@iden3/js-crypto": "1.3.2",
        "@iden3/js-iden3-core": "1.8.0",
        "@iden3/js-jsonld-merklization": "1.7.2",
        "@iden3/js-jwz": "1.12.2",
        "@iden3/js-merkletree": "1.5.1",
        "ffjavascript": "0.3.1",
        "rfc4648": "1.5.4",
        "snarkjs": "0.7.5"
      }
    },
    "node_modules/@0xpolygonid/js-sdk/node_modules/@noble/curves": {
      "version": "1.9.2",
      "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@noble/hashes": "1.8.0"
      },
      "engines": {
        "node": "^14.21.3 || >=16"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/@0xpolygonid/js-sdk/node_modules/@noble/hashes": {
      "version": "1.8.0",
      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": "^14.21.3 || >=16"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/@0xpolygonid/js-sdk/node_modules/ethers": {
      "version": "6.15.0",
      "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.15.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://github.com/sponsors/ethers-io/"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@adraffy/ens-normalize": "1.10.1",
        "@noble/curves": "1.2.0",
        "@noble/hashes": "1.3.2",
        "@types/node": "22.7.5",
        "aes-js": "4.0.0-beta.5",
        "tslib": "2.7.0",
        "ws": "8.17.1"
      },
      "engines": {
        "node": ">=14.0.0"
      }
    },
    "node_modules/@0xpolygonid/js-sdk/node_modules/ethers/node_modules/@noble/curves": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@noble/hashes": "1.3.2"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/@0xpolygonid/js-sdk/node_modules/ethers/node_modules/@noble/hashes": {
      "version": "1.3.2",
      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 16"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/@0xpolygonid/js-sdk/node_modules/tslib": {
      "version": "2.7.0",
      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "0BSD"
    },
    "node_modules/@0xpolygonid/js-sdk/node_modules/uuid": {
      "version": "13.0.0",
      "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        "https://github.com/sponsors/broofa",
        "https://github.com/sponsors/ctavan"
      ],
      "license": "MIT",
      "bin": {
        "uuid": "dist-node/bin/uuid"
      }
    },
    "node_modules/@adraffy/ens-normalize": {
      "version": "1.10.1",
      "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/@babel/runtime": {
      "version": "7.28.6",
      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@digitalbazaar/http-client": {
      "version": "3.4.1",
      "resolved": "https://registry.npmjs.org/@digitalbazaar/http-client/-/http-client-3.4.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-3-Clause",
      "dependencies": {
        "ky": "^0.33.3",
        "ky-universal": "^0.11.0",
        "undici": "^5.21.2"
      },
      "engines": {
        "node": ">=14.0"
      }
    },
    "node_modules/@ethersproject/abi": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/address": "^5.8.0",
        "@ethersproject/bignumber": "^5.8.0",
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/constants": "^5.8.0",
        "@ethersproject/hash": "^5.8.0",
        "@ethersproject/keccak256": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/properties": "^5.8.0",
        "@ethersproject/strings": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/abstract-provider": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bignumber": "^5.8.0",
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/networks": "^5.8.0",
        "@ethersproject/properties": "^5.8.0",
        "@ethersproject/transactions": "^5.8.0",
        "@ethersproject/web": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/abstract-signer": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/abstract-provider": "^5.8.0",
        "@ethersproject/bignumber": "^5.8.0",
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/properties": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/address": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bignumber": "^5.8.0",
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/keccak256": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/rlp": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/base64": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bytes": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/basex": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/properties": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/bignumber": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "bn.js": "^5.2.1"
      }
    },
    "node_modules/@ethersproject/bytes": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/logger": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/constants": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bignumber": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/contracts": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/abi": "^5.8.0",
        "@ethersproject/abstract-provider": "^5.8.0",
        "@ethersproject/abstract-signer": "^5.8.0",
        "@ethersproject/address": "^5.8.0",
        "@ethersproject/bignumber": "^5.8.0",
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/constants": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/properties": "^5.8.0",
        "@ethersproject/transactions": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/hash": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/abstract-signer": "^5.8.0",
        "@ethersproject/address": "^5.8.0",
        "@ethersproject/base64": "^5.8.0",
        "@ethersproject/bignumber": "^5.8.0",
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/keccak256": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/properties": "^5.8.0",
        "@ethersproject/strings": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/hdnode": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/abstract-signer": "^5.8.0",
        "@ethersproject/basex": "^5.8.0",
        "@ethersproject/bignumber": "^5.8.0",
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/pbkdf2": "^5.8.0",
        "@ethersproject/properties": "^5.8.0",
        "@ethersproject/sha2": "^5.8.0",
        "@ethersproject/signing-key": "^5.8.0",
        "@ethersproject/strings": "^5.8.0",
        "@ethersproject/transactions": "^5.8.0",
        "@ethersproject/wordlists": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/json-wallets": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/abstract-signer": "^5.8.0",
        "@ethersproject/address": "^5.8.0",
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/hdnode": "^5.8.0",
        "@ethersproject/keccak256": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/pbkdf2": "^5.8.0",
        "@ethersproject/properties": "^5.8.0",
        "@ethersproject/random": "^5.8.0",
        "@ethersproject/strings": "^5.8.0",
        "@ethersproject/transactions": "^5.8.0",
        "aes-js": "3.0.0",
        "scrypt-js": "3.0.1"
      }
    },
    "node_modules/@ethersproject/json-wallets/node_modules/aes-js": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/@ethersproject/keccak256": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bytes": "^5.8.0",
        "js-sha3": "0.8.0"
      }
    },
    "node_modules/@ethersproject/logger": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT"
    },
    "node_modules/@ethersproject/networks": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/logger": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/pbkdf2": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/sha2": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/properties": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/logger": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/providers": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/abstract-provider": "^5.8.0",
        "@ethersproject/abstract-signer": "^5.8.0",
        "@ethersproject/address": "^5.8.0",
        "@ethersproject/base64": "^5.8.0",
        "@ethersproject/basex": "^5.8.0",
        "@ethersproject/bignumber": "^5.8.0",
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/constants": "^5.8.0",
        "@ethersproject/hash": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/networks": "^5.8.0",
        "@ethersproject/properties": "^5.8.0",
        "@ethersproject/random": "^5.8.0",
        "@ethersproject/rlp": "^5.8.0",
        "@ethersproject/sha2": "^5.8.0",
        "@ethersproject/strings": "^5.8.0",
        "@ethersproject/transactions": "^5.8.0",
        "@ethersproject/web": "^5.8.0",
        "bech32": "1.1.4",
        "ws": "8.18.0"
      }
    },
    "node_modules/@ethersproject/providers/node_modules/ws": {
      "version": "8.18.0",
      "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=10.0.0"
      },
      "peerDependencies": {
        "bufferutil": "^4.0.1",
        "utf-8-validate": ">=5.0.2"
      },
      "peerDependenciesMeta": {
        "bufferutil": {
          "optional": true
        },
        "utf-8-validate": {
          "optional": true
        }
      }
    },
    "node_modules/@ethersproject/random": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/logger": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/rlp": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/logger": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/sha2": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "hash.js": "1.1.7"
      }
    },
    "node_modules/@ethersproject/signing-key": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/properties": "^5.8.0",
        "bn.js": "^5.2.1",
        "elliptic": "6.6.1",
        "hash.js": "1.1.7"
      }
    },
    "node_modules/@ethersproject/solidity": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bignumber": "^5.8.0",
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/keccak256": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/sha2": "^5.8.0",
        "@ethersproject/strings": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/strings": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/constants": "^5.8.0",
        "@ethersproject/logger": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/transactions": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/address": "^5.8.0",
        "@ethersproject/bignumber": "^5.8.0",
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/constants": "^5.8.0",
        "@ethersproject/keccak256": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/properties": "^5.8.0",
        "@ethersproject/rlp": "^5.8.0",
        "@ethersproject/signing-key": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/units": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bignumber": "^5.8.0",
        "@ethersproject/constants": "^5.8.0",
        "@ethersproject/logger": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/wallet": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/abstract-provider": "^5.8.0",
        "@ethersproject/abstract-signer": "^5.8.0",
        "@ethersproject/address": "^5.8.0",
        "@ethersproject/bignumber": "^5.8.0",
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/hash": "^5.8.0",
        "@ethersproject/hdnode": "^5.8.0",
        "@ethersproject/json-wallets": "^5.8.0",
        "@ethersproject/keccak256": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/properties": "^5.8.0",
        "@ethersproject/random": "^5.8.0",
        "@ethersproject/signing-key": "^5.8.0",
        "@ethersproject/transactions": "^5.8.0",
        "@ethersproject/wordlists": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/web": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/base64": "^5.8.0",
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/properties": "^5.8.0",
        "@ethersproject/strings": "^5.8.0"
      }
    },
    "node_modules/@ethersproject/wordlists": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/bytes": "^5.8.0",
        "@ethersproject/hash": "^5.8.0",
        "@ethersproject/logger": "^5.8.0",
        "@ethersproject/properties": "^5.8.0",
        "@ethersproject/strings": "^5.8.0"
      }
    },
    "node_modules/@fastify/busboy": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=14"
      }
    },
    "node_modules/@iden3/bigarray": {
      "version": "0.0.2",
      "resolved": "https://registry.npmjs.org/@iden3/bigarray/-/bigarray-0.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "GPL-3.0",
      "peer": true
    },
    "node_modules/@iden3/binfileutils": {
      "version": "0.0.12",
      "resolved": "https://registry.npmjs.org/@iden3/binfileutils/-/binfileutils-0.0.12.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "GPL-3.0",
      "peer": true,
      "dependencies": {
        "fastfile": "0.0.20",
        "ffjavascript": "^0.3.0"
      }
    },
    "node_modules/@iden3/js-crypto": {
      "version": "1.3.2",
      "resolved": "https://registry.npmjs.org/@iden3/js-crypto/-/js-crypto-1.3.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "AGPL-3.0",
      "dependencies": {
        "@noble/hashes": "^2.0.1"
      }
    },
    "node_modules/@iden3/js-iden3-auth": {
      "version": "1.14.0",
      "resolved": "https://registry.npmjs.org/@iden3/js-iden3-auth/-/js-iden3-auth-1.14.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT or Apache-2.0",
      "dependencies": {
        "@0xpolygonid/js-sdk": "1.39.4",
        "@iden3/js-crypto": "1.3.2",
        "@iden3/js-iden3-core": "1.8.0",
        "@iden3/js-jsonld-merklization": "1.7.2",
        "@iden3/js-jwz": "1.12.2",
        "@iden3/js-merkletree": "1.5.1",
        "did-resolver": "^4.1.0",
        "ethers": "^5.7.2",
        "tslib": "^2.6.2",
        "uuid": "^9.0.1"
      }
    },
    "node_modules/@iden3/js-iden3-auth/node_modules/@0xpolygonid/js-sdk": {
      "version": "1.39.4",
      "resolved": "https://registry.npmjs.org/@0xpolygonid/js-sdk/-/js-sdk-1.39.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT or Apache-2.0",
      "dependencies": {
        "@iden3/onchain-non-merklized-issuer-base-abi": "0.0.3",
        "@iden3/universal-verifier-v2-abi": "2.0.2",
        "@noble/curves": "1.9.2",
        "@solana/web3.js": "1.98.4",
        "ajv": "8.17.1",
        "ajv-formats": "3.0.1",
        "borsh": "0.7.0",
        "canonicalize": "^2.1.0",
        "did-jwt": "8.0.18",
        "did-resolver": "4.1.0",
        "ethers": "6.15.0",
        "idb-keyval": "6.2.2",
        "jose": "^6.1.0",
        "jsonld": "8.3.3",
        "pubsub-js": "1.9.5",
        "quick-lru": "7.0.1",
        "uuid": "13.0.0"
      },
      "engines": {
        "node": ">=20.11.0"
      },
      "peerDependencies": {
        "@iden3/js-crypto": "1.3.2",
        "@iden3/js-iden3-core": "1.8.0",
        "@iden3/js-jsonld-merklization": "1.7.2",
        "@iden3/js-jwz": "1.12.2",
        "@iden3/js-merkletree": "1.5.1",
        "ffjavascript": "0.3.1",
        "rfc4648": "1.5.4",
        "snarkjs": "0.7.5"
      }
    },
    "node_modules/@iden3/js-iden3-auth/node_modules/@0xpolygonid/js-sdk/node_modules/@noble/hashes": {
      "version": "1.3.2",
      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 16"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/@iden3/js-iden3-auth/node_modules/@0xpolygonid/js-sdk/node_modules/ethers": {
      "version": "6.15.0",
      "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.15.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://github.com/sponsors/ethers-io/"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@adraffy/ens-normalize": "1.10.1",
        "@noble/curves": "1.2.0",
        "@noble/hashes": "1.3.2",
        "@types/node": "22.7.5",
        "aes-js": "4.0.0-beta.5",
        "tslib": "2.7.0",
        "ws": "8.17.1"
      },
      "engines": {
        "node": ">=14.0.0"
      }
    },
    "node_modules/@iden3/js-iden3-auth/node_modules/@0xpolygonid/js-sdk/node_modules/ethers/node_modules/@noble/curves": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@noble/hashes": "1.3.2"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/@iden3/js-iden3-auth/node_modules/@0xpolygonid/js-sdk/node_modules/uuid": {
      "version": "13.0.0",
      "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        "https://github.com/sponsors/broofa",
        "https://github.com/sponsors/ctavan"
      ],
      "license": "MIT",
      "bin": {
        "uuid": "dist-node/bin/uuid"
      }
    },
    "node_modules/@iden3/js-iden3-auth/node_modules/@noble/curves": {
      "version": "1.9.2",
      "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@noble/hashes": "1.8.0"
      },
      "engines": {
        "node": "^14.21.3 || >=16"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/@iden3/js-iden3-auth/node_modules/@noble/hashes": {
      "version": "1.8.0",
      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": "^14.21.3 || >=16"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/@iden3/js-iden3-auth/node_modules/ethers": {
      "version": "5.8.0",
      "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@ethersproject/abi": "5.8.0",
        "@ethersproject/abstract-provider": "5.8.0",
        "@ethersproject/abstract-signer": "5.8.0",
        "@ethersproject/address": "5.8.0",
        "@ethersproject/base64": "5.8.0",
        "@ethersproject/basex": "5.8.0",
        "@ethersproject/bignumber": "5.8.0",
        "@ethersproject/bytes": "5.8.0",
        "@ethersproject/constants": "5.8.0",
        "@ethersproject/contracts": "5.8.0",
        "@ethersproject/hash": "5.8.0",
        "@ethersproject/hdnode": "5.8.0",
        "@ethersproject/json-wallets": "5.8.0",
        "@ethersproject/keccak256": "5.8.0",
        "@ethersproject/logger": "5.8.0",
        "@ethersproject/networks": "5.8.0",
        "@ethersproject/pbkdf2": "5.8.0",
        "@ethersproject/properties": "5.8.0",
        "@ethersproject/providers": "5.8.0",
        "@ethersproject/random": "5.8.0",
        "@ethersproject/rlp": "5.8.0",
        "@ethersproject/sha2": "5.8.0",
        "@ethersproject/signing-key": "5.8.0",
        "@ethersproject/solidity": "5.8.0",
        "@ethersproject/strings": "5.8.0",
        "@ethersproject/transactions": "5.8.0",
        "@ethersproject/units": "5.8.0",
        "@ethersproject/wallet": "5.8.0",
        "@ethersproject/web": "5.8.0",
        "@ethersproject/wordlists": "5.8.0"
      }
    },
    "node_modules/@iden3/js-iden3-auth/node_modules/tslib": {
      "version": "2.7.0",
      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "0BSD"
    },
    "node_modules/@iden3/js-iden3-auth/node_modules/uuid": {
      "version": "9.0.1",
      "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        "https://github.com/sponsors/broofa",
        "https://github.com/sponsors/ctavan"
      ],
      "license": "MIT",
      "bin": {
        "uuid": "dist/bin/uuid"
      }
    },
    "node_modules/@iden3/js-iden3-core": {
      "version": "1.8.0",
      "resolved": "https://registry.npmjs.org/@iden3/js-iden3-core/-/js-iden3-core-1.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT or Apache-2.0",
      "peerDependencies": {
        "@iden3/js-crypto": "1.3.2"
      }
    },
    "node_modules/@iden3/js-jsonld-merklization": {
      "version": "1.7.2",
      "resolved": "https://registry.npmjs.org/@iden3/js-jsonld-merklization/-/js-jsonld-merklization-1.7.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT or Apache-2.0",
      "dependencies": {
        "@js-temporal/polyfill": "0.5.1",
        "jsonld": "8.3.3",
        "n3": "1.26.0"
      },
      "peerDependencies": {
        "@iden3/js-crypto": "1.3.2",
        "@iden3/js-merkletree": "1.5.1"
      }
    },
    "node_modules/@iden3/js-jwz": {
      "version": "1.12.2",
      "resolved": "https://registry.npmjs.org/@iden3/js-jwz/-/js-jwz-1.12.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "AGPL-3.0",
      "peerDependencies": {
        "@iden3/js-crypto": "1.3.2",
        "@iden3/js-iden3-core": "1.8.0",
        "@iden3/js-merkletree": "1.5.1",
        "@noble/curves": "^1.9.2",
        "ffjavascript": "0.3.1",
        "rfc4648": "1.5.4",
        "snarkjs": "0.7.5"
      }
    },
    "node_modules/@iden3/js-merkletree": {
      "version": "1.5.1",
      "resolved": "https://registry.npmjs.org/@iden3/js-merkletree/-/js-merkletree-1.5.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT or Apache-2.0",
      "peerDependencies": {
        "@iden3/js-crypto": "1.3.2",
        "idb-keyval": "6.2.2"
      }
    },
    "node_modules/@iden3/onchain-non-merklized-issuer-base-abi": {
      "version": "0.0.3",
      "resolved": "https://registry.npmjs.org/@iden3/onchain-non-merklized-issuer-base-abi/-/onchain-non-merklized-issuer-base-abi-0.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT or Apache-2.0"
    },
    "node_modules/@iden3/universal-verifier-v2-abi": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/@iden3/universal-verifier-v2-abi/-/universal-verifier-v2-abi-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT or Apache-2.0"
    },
    "node_modules/@js-temporal/polyfill": {
      "version": "0.5.1",
      "resolved": "https://registry.npmjs.org/@js-temporal/polyfill/-/polyfill-0.5.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC",
      "dependencies": {
        "jsbi": "^4.3.0"
      },
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/@multiformats/base-x": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/@multiformats/base-x/-/base-x-4.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/@noble/ciphers": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": "^14.21.3 || >=16"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/@noble/curves": {
      "version": "1.9.7",
      "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@noble/hashes": "1.8.0"
      },
      "engines": {
        "node": "^14.21.3 || >=16"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/@noble/curves/node_modules/@noble/hashes": {
      "version": "1.8.0",
      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": "^14.21.3 || >=16"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/@noble/hashes": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 20.19.0"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/@scure/base": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/@scure/base/-/base-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/@solana/buffer-layout": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "buffer": "~6.0.3"
      },
      "engines": {
        "node": ">=5.10"
      }
    },
    "node_modules/@solana/codecs-core": {
      "version": "2.3.0",
      "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@solana/errors": "2.3.0"
      },
      "engines": {
        "node": ">=20.18.0"
      },
      "peerDependencies": {
        "typescript": ">=5.3.3"
      }
    },
    "node_modules/@solana/codecs-numbers": {
      "version": "2.3.0",
      "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@solana/codecs-core": "2.3.0",
        "@solana/errors": "2.3.0"
      },
      "engines": {
        "node": ">=20.18.0"
      },
      "peerDependencies": {
        "typescript": ">=5.3.3"
      }
    },
    "node_modules/@solana/errors": {
      "version": "2.3.0",
      "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "chalk": "^5.4.1",
        "commander": "^14.0.0"
      },
      "bin": {
        "errors": "bin/cli.mjs"
      },
      "engines": {
        "node": ">=20.18.0"
      },
      "peerDependencies": {
        "typescript": ">=5.3.3"
      }
    },
    "node_modules/@solana/web3.js": {
      "version": "1.98.4",
      "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.98.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@babel/runtime": "^7.25.0",
        "@noble/curves": "^1.4.2",
        "@noble/hashes": "^1.4.0",
        "@solana/buffer-layout": "^4.0.1",
        "@solana/codecs-numbers": "^2.1.0",
        "agentkeepalive": "^4.5.0",
        "bn.js": "^5.2.1",
        "borsh": "^0.7.0",
        "bs58": "^4.0.1",
        "buffer": "6.0.3",
        "fast-stable-stringify": "^1.0.0",
        "jayson": "^4.1.1",
        "node-fetch": "^2.7.0",
        "rpc-websockets": "^9.0.2",
        "superstruct": "^2.0.2"
      }
    },
    "node_modules/@solana/web3.js/node_modules/@noble/hashes": {
      "version": "1.8.0",
      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": "^14.21.3 || >=16"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/@swc/helpers": {
      "version": "0.5.19",
      "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.19.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0",
      "dependencies": {
        "tslib": "^2.8.0"
      }
    },
    "node_modules/@types/connect": {
      "version": "3.4.38",
      "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@types/node": "*"
      }
    },
    "node_modules/@types/node": {
      "version": "22.7.5",
      "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "undici-types": "~6.19.2"
      }
    },
    "node_modules/@types/uuid": {
      "version": "10.0.0",
      "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/@types/ws": {
      "version": "7.4.7",
      "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@types/node": "*"
      }
    },
    "node_modules/abort-controller": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "event-target-shim": "^5.0.0"
      },
      "engines": {
        "node": ">=6.5"
      }
    },
    "node_modules/aes-js": {
      "version": "4.0.0-beta.5",
      "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/agentkeepalive": {
      "version": "4.6.0",
      "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "humanize-ms": "^1.2.1"
      },
      "engines": {
        "node": ">= 8.0.0"
      }
    },
    "node_modules/ajv": {
      "version": "8.17.1",
      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "fast-deep-equal": "^3.1.3",
        "fast-uri": "^3.0.1",
        "json-schema-traverse": "^1.0.0",
        "require-from-string": "^2.0.2"
      },
      "funding": {
        "type": "github",
        "url": "https://github.com/sponsors/epoberezkin"
      }
    },
    "node_modules/ajv-formats": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "ajv": "^8.0.0"
      },
      "peerDependencies": {
        "ajv": "^8.0.0"
      },
      "peerDependenciesMeta": {
        "ajv": {
          "optional": true
        }
      }
    },
    "node_modules/async": {
      "version": "3.2.6",
      "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peer": true
    },
    "node_modules/b4a": {
      "version": "1.8.0",
      "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0",
      "peer": true,
      "peerDependencies": {
        "react-native-b4a": "*"
      },
      "peerDependenciesMeta": {
        "react-native-b4a": {
          "optional": true
        }
      }
    },
    "node_modules/balanced-match": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peer": true
    },
    "node_modules/base-x": {
      "version": "3.0.11",
      "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "safe-buffer": "^5.0.1"
      }
    },
    "node_modules/base64-js": {
      "version": "1.5.1",
      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/feross"
        },
        {
          "type": "patreon",
          "url": "https://www.patreon.com/feross"
        },
        {
          "type": "consulting",
          "url": "https://feross.org/support"
        }
      ],
      "license": "MIT"
    },
    "node_modules/bech32": {
      "version": "1.1.4",
      "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/bfj": {
      "version": "7.1.0",
      "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peer": true,
      "dependencies": {
        "bluebird": "^3.7.2",
        "check-types": "^11.2.3",
        "hoopy": "^0.1.4",
        "jsonpath": "^1.1.1",
        "tryer": "^1.0.1"
      },
      "engines": {
        "node": ">= 8.0.0"
      }
    },
    "node_modules/blake2b-wasm": {
      "version": "2.4.0",
      "resolved": "https://registry.npmjs.org/blake2b-wasm/-/blake2b-wasm-2.4.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peer": true,
      "dependencies": {
        "b4a": "^1.0.1",
        "nanoassert": "^2.0.0"
      }
    },
    "node_modules/bluebird": {
      "version": "3.7.2",
      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peer": true
    },
    "node_modules/bn.js": {
      "version": "5.2.3",
      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/borsh": {
      "version": "0.7.0",
      "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0",
      "dependencies": {
        "bn.js": "^5.2.0",
        "bs58": "^4.0.0",
        "text-encoding-utf-8": "^1.0.2"
      }
    },
    "node_modules/brace-expansion": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peer": true,
      "dependencies": {
        "balanced-match": "^1.0.0"
      }
    },
    "node_modules/brorand": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/bs58": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "base-x": "^3.0.2"
      }
    },
    "node_modules/buffer": {
      "version": "6.0.3",
      "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/feross"
        },
        {
          "type": "patreon",
          "url": "https://www.patreon.com/feross"
        },
        {
          "type": "consulting",
          "url": "https://feross.org/support"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "base64-js": "^1.3.1",
        "ieee754": "^1.2.1"
      }
    },
    "node_modules/bufferutil": {
      "version": "4.1.0",
      "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "hasInstallScript": true,
      "license": "MIT",
      "optional": true,
      "dependencies": {
        "node-gyp-build": "^4.3.0"
      },
      "engines": {
        "node": ">=6.14.2"
      }
    },
    "node_modules/canonicalize": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-2.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0",
      "bin": {
        "canonicalize": "bin/canonicalize.js"
      }
    },
    "node_modules/chalk": {
      "version": "5.6.2",
      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": "^12.17.0 || ^14.13 || >=16.0.0"
      },
      "funding": {
        "url": "https://github.com/chalk/chalk?sponsor=1"
      }
    },
    "node_modules/check-types": {
      "version": "11.2.3",
      "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peer": true
    },
    "node_modules/circom_runtime": {
      "version": "0.1.28",
      "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.28.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0",
      "peer": true,
      "dependencies": {
        "ffjavascript": "0.3.1"
      },
      "bin": {
        "calcwit": "calcwit.js"
      }
    },
    "node_modules/commander": {
      "version": "14.0.3",
      "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=20"
      }
    },
    "node_modules/data-uri-to-buffer": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 12"
      }
    },
    "node_modules/delay": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/did-jwt": {
      "version": "8.0.18",
      "resolved": "https://registry.npmjs.org/did-jwt/-/did-jwt-8.0.18.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0",
      "dependencies": {
        "@noble/ciphers": "^1.0.0",
        "@noble/curves": "^1.0.0",
        "@noble/hashes": "^1.3.0",
        "@scure/base": "^2.0.0",
        "canonicalize": "^2.0.0",
        "did-resolver": "^4.1.0",
        "multibase": "^4.0.6",
        "multiformats": "^9.6.2",
        "uint8arrays": "3.1.1"
      }
    },
    "node_modules/did-jwt/node_modules/@noble/hashes": {
      "version": "1.8.0",
      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": "^14.21.3 || >=16"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/did-resolver": {
      "version": "4.1.0",
      "resolved": "https://registry.npmjs.org/did-resolver/-/did-resolver-4.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0"
    },
    "node_modules/ejs": {
      "version": "3.1.10",
      "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0",
      "peer": true,
      "dependencies": {
        "jake": "^10.8.5"
      },
      "bin": {
        "ejs": "bin/cli.js"
      },
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/elliptic": {
      "version": "6.6.1",
      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "bn.js": "^4.11.9",
        "brorand": "^1.1.0",
        "hash.js": "^1.0.0",
        "hmac-drbg": "^1.0.1",
        "inherits": "^2.0.4",
        "minimalistic-assert": "^1.0.1",
        "minimalistic-crypto-utils": "^1.0.1"
      }
    },
    "node_modules/elliptic/node_modules/bn.js": {
      "version": "4.12.3",
      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/es6-promise": {
      "version": "4.2.8",
      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/es6-promisify": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "es6-promise": "^4.0.3"
      }
    },
    "node_modules/escodegen": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-2-Clause",
      "peer": true,
      "dependencies": {
        "esprima": "^4.0.1",
        "estraverse": "^5.2.0",
        "esutils": "^2.0.2"
      },
      "bin": {
        "escodegen": "bin/escodegen.js",
        "esgenerate": "bin/esgenerate.js"
      },
      "engines": {
        "node": ">=6.0"
      },
      "optionalDependencies": {
        "source-map": "~0.6.1"
      }
    },
    "node_modules/escodegen/node_modules/esprima": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-2-Clause",
      "peer": true,
      "bin": {
        "esparse": "bin/esparse.js",
        "esvalidate": "bin/esvalidate.js"
      },
      "engines": {
        "node": ">=4"
      }
    },
    "node_modules/esprima": {
      "version": "1.2.5",
      "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz",
      "integrity": [REDACTED_SECRET],
      "peer": true,
      "bin": {
        "esparse": "bin/esparse.js",
        "esvalidate": "bin/esvalidate.js"
      },
      "engines": {
        "node": ">=0.4.0"
      }
    },
    "node_modules/estraverse": {
      "version": "5.3.0",
      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-2-Clause",
      "peer": true,
      "engines": {
        "node": ">=4.0"
      }
    },
    "node_modules/esutils": {
      "version": "2.0.3",
      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-2-Clause",
      "peer": true,
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/ethers": {
      "version": "6.16.0",
      "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.16.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "individual",
          "url": "https://github.com/sponsors/ethers-io/"
        },
        {
          "type": "individual",
          "url": "https://www.buymeacoffee.com/ricmoo"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@adraffy/ens-normalize": "1.10.1",
        "@noble/curves": "1.2.0",
        "@noble/hashes": "1.3.2",
        "@types/node": "22.7.5",
        "aes-js": "4.0.0-beta.5",
        "tslib": "2.7.0",
        "ws": "8.17.1"
      },
      "engines": {
        "node": ">=14.0.0"
      }
    },
    "node_modules/ethers/node_modules/@noble/curves": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@noble/hashes": "1.3.2"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/ethers/node_modules/@noble/hashes": {
      "version": "1.3.2",
      "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 16"
      },
      "funding": {
        "url": "https://paulmillr.com/funding/"
      }
    },
    "node_modules/ethers/node_modules/tslib": {
      "version": "2.7.0",
      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "0BSD"
    },
    "node_modules/event-target-shim": {
      "version": "5.0.1",
      "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/eventemitter3": {
      "version": "5.0.4",
      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/events": {
      "version": "3.3.0",
      "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=0.8.x"
      }
    },
    "node_modules/eyes": {
      "version": "0.1.8",
      "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
      "integrity": [REDACTED_SECRET],
      "engines": {
        "node": "> 0.1.90"
      }
    },
    "node_modules/fast-deep-equal": {
      "version": "3.1.3",
      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/fast-stable-stringify": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/fast-uri": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/fastify"
        },
        {
          "type": "opencollective",
          "url": "https://opencollective.com/fastify"
        }
      ],
      "license": "BSD-3-Clause"
    },
    "node_modules/fastfile": {
      "version": "0.0.20",
      "resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.20.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "GPL-3.0",
      "peer": true
    },
    "node_modules/fetch-blob": {
      "version": "3.2.0",
      "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/jimmywarting"
        },
        {
          "type": "paypal",
          "url": "https://paypal.me/jimmywarting"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "node-domexception": "^1.0.0",
        "web-streams-polyfill": "^3.0.3"
      },
      "engines": {
        "node": "^12.20 || >= 14.13"
      }
    },
    "node_modules/ffjavascript": {
      "version": "0.3.1",
      "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.3.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "GPL-3.0",
      "peer": true,
      "dependencies": {
        "wasmbuilder": "0.0.16",
        "wasmcurves": "0.2.2",
        "web-worker": "1.2.0"
      }
    },
    "node_modules/filelist": {
      "version": "1.0.6",
      "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0",
      "peer": true,
      "dependencies": {
        "minimatch": "^5.0.1"
      }
    },
    "node_modules/formdata-polyfill": {
      "version": "4.0.10",
      "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "fetch-blob": "^3.1.2"
      },
      "engines": {
        "node": ">=12.20.0"
      }
    },
    "node_modules/hash.js": {
      "version": "1.1.7",
      "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "inherits": "^2.0.3",
        "minimalistic-assert": "^1.0.1"
      }
    },
    "node_modules/hmac-drbg": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "hash.js": "^1.0.3",
        "minimalistic-assert": "^1.0.0",
        "minimalistic-crypto-utils": "^1.0.1"
      }
    },
    "node_modules/hoopy": {
      "version": "0.1.4",
      "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peer": true,
      "engines": {
        "node": ">= 6.0.0"
      }
    },
    "node_modules/humanize-ms": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "ms": "^2.0.0"
      }
    },
    "node_modules/idb-keyval": {
      "version": "6.2.2",
      "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0"
    },
    "node_modules/ieee754": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/feross"
        },
        {
          "type": "patreon",
          "url": "https://www.patreon.com/feross"
        },
        {
          "type": "consulting",
          "url": "https://feross.org/support"
        }
      ],
      "license": "BSD-3-Clause"
    },
    "node_modules/inherits": {
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/isomorphic-ws": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peerDependencies": {
        "ws": "*"
      }
    },
    "node_modules/jake": {
      "version": "10.9.4",
      "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0",
      "peer": true,
      "dependencies": {
        "async": "^3.2.6",
        "filelist": "^1.0.4",
        "picocolors": "^1.1.1"
      },
      "bin": {
        "jake": "bin/cli.js"
      },
      "engines": {
        "node": ">=10"
      }
    },
    "node_modules/jayson": {
      "version": "4.3.0",
      "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@types/connect": "^3.4.33",
        "@types/node": "^12.12.54",
        "@types/ws": "^7.4.4",
        "commander": "^2.20.3",
        "delay": "^5.0.0",
        "es6-promisify": "^5.0.0",
        "eyes": "^0.1.8",
        "isomorphic-ws": "^4.0.1",
        "json-stringify-safe": "^5.0.1",
        "stream-json": "^1.9.1",
        "uuid": "^8.3.2",
        "ws": "^7.5.10"
      },
      "bin": {
        "jayson": "bin/jayson.js"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/jayson/node_modules/@types/node": {
      "version": "12.20.55",
      "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/jayson/node_modules/commander": {
      "version": "2.20.3",
      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/jayson/node_modules/utf-8-validate": {
      "version": "5.0.10",
      "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
      "integrity": [REDACTED_SECRET],
      "hasInstallScript": true,
      "license": "MIT",
      "optional": true,
      "peer": true,
      "dependencies": {
        "node-gyp-build": "^4.3.0"
      },
      "engines": {
        "node": ">=6.14.2"
      }
    },
    "node_modules/jayson/node_modules/uuid": {
      "version": "8.3.2",
      "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "bin": {
        "uuid": "dist/bin/uuid"
      }
    },
    "node_modules/jayson/node_modules/ws": {
      "version": "7.5.10",
      "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=8.3.0"
      },
      "peerDependencies": {
        "bufferutil": "^4.0.1",
        "utf-8-validate": "^5.0.2"
      },
      "peerDependenciesMeta": {
        "bufferutil": {
          "optional": true
        },
        "utf-8-validate": {
          "optional": true
        }
      }
    },
    "node_modules/jose": {
      "version": "6.2.1",
      "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/panva"
      }
    },
    "node_modules/js-sha3": {
      "version": "0.8.0",
      "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/jsbi": {
      "version": "4.3.2",
      "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-4.3.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0"
    },
    "node_modules/json-schema-traverse": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/json-stringify-safe": {
      "version": "5.0.1",
      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/jsonld": {
      "version": "8.3.3",
      "resolved": "https://registry.npmjs.org/jsonld/-/jsonld-8.3.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-3-Clause",
      "dependencies": {
        "@digitalbazaar/http-client": "^3.4.1",
        "canonicalize": "^1.0.1",
        "lru-cache": "^6.0.0",
        "rdf-canonize": "^3.4.0"
      },
      "engines": {
        "node": ">=14"
      }
    },
    "node_modules/jsonld/node_modules/canonicalize": {
      "version": "1.0.8",
      "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-1.0.8.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0"
    },
    "node_modules/jsonpath": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peer": true,
      "dependencies": {
        "esprima": "1.2.5",
        "static-eval": "2.1.1",
        "underscore": "1.13.6"
      }
    },
    "node_modules/ky": {
      "version": "0.33.3",
      "resolved": "https://registry.npmjs.org/ky/-/ky-0.33.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=14.16"
      },
      "funding": {
        "url": "https://github.com/sindresorhus/ky?sponsor=1"
      }
    },
    "node_modules/ky-universal": {
      "version": "0.11.0",
      "resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.11.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "abort-controller": "^3.0.0",
        "node-fetch": "^3.2.10"
      },
      "engines": {
        "node": ">=14.16"
      },
      "funding": {
        "url": "https://github.com/sindresorhus/ky-universal?sponsor=1"
      },
      "peerDependencies": {
        "ky": ">=0.31.4",
        "web-streams-polyfill": ">=3.2.1"
      },
      "peerDependenciesMeta": {
        "web-streams-polyfill": {
          "optional": true
        }
      }
    },
    "node_modules/ky-universal/node_modules/node-fetch": {
      "version": "3.3.2",
      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "data-uri-to-buffer": "^4.0.0",
        "fetch-blob": "^3.1.4",
        "formdata-polyfill": "^4.0.10"
      },
      "engines": {
        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/node-fetch"
      }
    },
    "node_modules/logplease": {
      "version": "1.2.15",
      "resolved": "https://registry.npmjs.org/logplease/-/logplease-1.2.15.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peer": true
    },
    "node_modules/lru-cache": {
      "version": "6.0.0",
      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC",
      "dependencies": {
        "yallist": "^4.0.0"
      },
      "engines": {
        "node": ">=10"
      }
    },
    "node_modules/minimalistic-assert": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    },
    "node_modules/minimalistic-crypto-utils": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/minimatch": {
      "version": "5.1.9",
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC",
      "peer": true,
      "dependencies": {
        "brace-expansion": "^2.0.1"
      },
      "engines": {
        "node": ">=10"
      }
    },
    "node_modules/ms": {
      "version": "2.1.3",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/multibase": {
      "version": "4.0.6",
      "resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.6.tgz",
      "integrity": [REDACTED_SECRET],
      "deprecated": "This module has been superseded by the multiformats module",
      "license": "MIT",
      "dependencies": {
        "@multiformats/base-x": "^4.0.1"
      },
      "engines": {
        "node": ">=12.0.0",
        "npm": ">=6.0.0"
      }
    },
    "node_modules/multiformats": {
      "version": "9.9.0",
      "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "(Apache-2.0 AND MIT)"
    },
    "node_modules/n3": {
      "version": "1.26.0",
      "resolved": "https://registry.npmjs.org/n3/-/n3-1.26.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "buffer": "^6.0.3",
        "readable-stream": "^4.0.0"
      },
      "engines": {
        "node": ">=12.0"
      }
    },
    "node_modules/nanoassert": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC",
      "peer": true
    },
    "node_modules/node-domexception": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "deprecated": "Use your platform's native DOMException instead",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/jimmywarting"
        },
        {
          "type": "github",
          "url": "https://paypal.me/jimmywarting"
        }
      ],
      "license": "MIT",
      "engines": {
        "node": ">=10.5.0"
      }
    },
    "node_modules/node-fetch": {
      "version": "2.7.0",
      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "whatwg-url": "^5.0.0"
      },
      "engines": {
        "node": "4.x || >=6.0.0"
      },
      "peerDependencies": {
        "encoding": "^0.1.0"
      },
      "peerDependenciesMeta": {
        "encoding": {
          "optional": true
        }
      }
    },
    "node_modules/node-gyp-build": {
      "version": "4.8.4",
      "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "optional": true,
      "bin": {
        "node-gyp-build": "bin.js",
        "node-gyp-build-optional": "optional.js",
        "node-gyp-build-test": "build-test.js"
      }
    },
    "node_modules/picocolors": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC",
      "peer": true
    },
    "node_modules/process": {
      "version": "0.11.10",
      "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 0.6.0"
      }
    },
    "node_modules/pubsub-js": {
      "version": "1.9.5",
      "resolved": "https://registry.npmjs.org/pubsub-js/-/pubsub-js-1.9.5.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/quick-lru": {
      "version": "7.0.1",
      "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-7.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=18"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/r1csfile": {
      "version": "0.0.48",
      "resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.48.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "GPL-3.0",
      "peer": true,
      "dependencies": {
        "@iden3/bigarray": "0.0.2",
        "@iden3/binfileutils": "0.0.12",
        "fastfile": "0.0.20",
        "ffjavascript": "0.3.0"
      }
    },
    "node_modules/r1csfile/node_modules/ffjavascript": {
      "version": "0.3.0",
      "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "GPL-3.0",
      "peer": true,
      "dependencies": {
        "wasmbuilder": "0.0.16",
        "wasmcurves": "0.2.2",
        "web-worker": "1.2.0"
      }
    },
    "node_modules/rdf-canonize": {
      "version": "3.4.0",
      "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-3.4.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-3-Clause",
      "dependencies": {
        "setimmediate": "^1.0.5"
      },
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/readable-stream": {
      "version": "4.7.0",
      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "abort-controller": "^3.0.0",
        "buffer": "^6.0.3",
        "events": "^3.3.0",
        "process": "^0.11.10",
        "string_decoder": "^1.3.0"
      },
      "engines": {
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
      }
    },
    "node_modules/require-from-string": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/rfc4648": {
      "version": "1.5.4",
      "resolved": "https://registry.npmjs.org/rfc4648/-/rfc4648-1.5.4.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peer": true
    },
    "node_modules/rpc-websockets": {
      "version": "9.3.5",
      "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.3.5.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "LGPL-3.0-only",
      "dependencies": {
        "@swc/helpers": "^0.5.11",
        "@types/uuid": "^10.0.0",
        "@types/ws": "^8.2.2",
        "buffer": "^6.0.3",
        "eventemitter3": "^5.0.1",
        "uuid": "^11.0.0",
        "ws": "^8.5.0"
      },
      "funding": {
        "type": "paypal",
        "url": "https://paypal.me/kozjak"
      },
      "optionalDependencies": {
        "bufferutil": "^4.0.1",
        "utf-8-validate": "^6.0.0"
      }
    },
    "node_modules/rpc-websockets/node_modules/@types/ws": {
      "version": "8.18.1",
      "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@types/node": "*"
      }
    },
    "node_modules/safe-buffer": {
      "version": "5.2.1",
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/feross"
        },
        {
          "type": "patreon",
          "url": "https://www.patreon.com/feross"
        },
        {
          "type": "consulting",
          "url": "https://feross.org/support"
        }
      ],
      "license": "MIT"
    },
    "node_modules/scrypt-js": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/setimmediate": {
      "version": "1.0.5",
      "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/snarkjs": {
      "version": "0.7.5",
      "resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.7.5.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "GPL-3.0",
      "peer": true,
      "dependencies": {
        "@iden3/binfileutils": "0.0.12",
        "bfj": "^7.0.2",
        "blake2b-wasm": "^2.4.0",
        "circom_runtime": "0.1.28",
        "ejs": "^3.1.6",
        "fastfile": "0.0.20",
        "ffjavascript": "0.3.1",
        "js-sha3": "^0.8.0",
        "logplease": "^1.2.15",
        "r1csfile": "0.0.48"
      },
      "bin": {
        "snarkjs": "build/cli.cjs"
      }
    },
    "node_modules/source-map": {
      "version": "0.6.1",
      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-3-Clause",
      "optional": true,
      "peer": true,
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/static-eval": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peer": true,
      "dependencies": {
        "escodegen": "^2.1.0"
      }
    },
    "node_modules/stream-chain": {
      "version": "2.2.5",
      "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-3-Clause"
    },
    "node_modules/stream-json": {
      "version": "1.9.1",
      "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-3-Clause",
      "dependencies": {
        "stream-chain": "^2.2.5"
      }
    },
    "node_modules/string_decoder": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "safe-buffer": "~5.2.0"
      }
    },
    "node_modules/superstruct": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=14.0.0"
      }
    },
    "node_modules/text-encoding-utf-8": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz",
      "integrity": [REDACTED_SECRET]
    },
    "node_modules/tr46": {
      "version": "0.0.3",
      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/tryer": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peer": true
    },
    "node_modules/tslib": {
      "version": "2.8.1",
      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "0BSD"
    },
    "node_modules/typescript": {
      "version": "5.9.3",
      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0",
      "peer": true,
      "bin": {
        "tsc": "bin/tsc",
        "tsserver": "bin/tsserver"
      },
      "engines": {
        "node": ">=14.17"
      }
    },
    "node_modules/uint8arrays": {
      "version": "3.1.1",
      "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "multiformats": "^9.4.2"
      }
    },
    "node_modules/underscore": {
      "version": "1.13.6",
      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "peer": true
    },
    "node_modules/undici": {
      "version": "5.29.0",
      "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "@fastify/busboy": "^2.0.0"
      },
      "engines": {
        "node": ">=14.0"
      }
    },
    "node_modules/undici-types": {
      "version": "6.19.8",
      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT"
    },
    "node_modules/utf-8-validate": {
      "version": "6.0.6",
      "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.6.tgz",
      "integrity": [REDACTED_SECRET],
      "hasInstallScript": true,
      "license": "MIT",
      "optional": true,
      "dependencies": {
        "node-gyp-build": "^4.3.0"
      },
      "engines": {
        "node": ">=6.14.2"
      }
    },
    "node_modules/uuid": {
      "version": "11.1.0",
      "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        "https://github.com/sponsors/broofa",
        "https://github.com/sponsors/ctavan"
      ],
      "license": "MIT",
      "bin": {
        "uuid": "dist/esm/bin/uuid"
      }
    },
    "node_modules/wasmbuilder": {
      "version": "0.0.16",
      "resolved": "https://registry.npmjs.org/wasmbuilder/-/wasmbuilder-0.0.16.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "GPL-3.0",
      "peer": true
    },
    "node_modules/wasmcurves": {
      "version": "0.2.2",
      "resolved": "https://registry.npmjs.org/wasmcurves/-/wasmcurves-0.2.2.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "GPL-3.0",
      "peer": true,
      "dependencies": {
        "wasmbuilder": "0.0.16"
      }
    },
    "node_modules/web-streams-polyfill": {
      "version": "3.3.3",
      "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/web-worker": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "Apache-2.0",
      "peer": true
    },
    "node_modules/webidl-conversions": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "BSD-2-Clause"
    },
    "node_modules/whatwg-url": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "dependencies": {
        "tr46": "~0.0.3",
        "webidl-conversions": "^3.0.0"
      }
    },
    "node_modules/ws": {
      "version": "8.17.1",
      "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=10.0.0"
      },
      "peerDependencies": {
        "bufferutil": "^4.0.1",
        "utf-8-validate": ">=5.0.2"
      },
      "peerDependenciesMeta": {
        "bufferutil": {
          "optional": true
        },
        "utf-8-validate": {
          "optional": true
        }
      }
    },
    "node_modules/yallist": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "ISC"
    }
  }
}


path: scripts/package.json
content: {
  "name": "verified-agent-identity",
  "version": "0.0.2",
  "description": "Billions OpenClaw verification skill",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "identity",
    "openclaw",
    "zk"
  ],
  "author": "BillionsNetwork",
  "license": "UNLICENSED",
  "dependencies": {
    "@0xpolygonid/js-sdk": "1.42.1",
    "@iden3/js-iden3-auth": "1.14.0",
    "@iden3/js-iden3-core": "1.8.0",
    "@noble/curves": "^1.9.2",
    "ethers": "^6.13.4",
    "uuid": "^11.0.3"
  }
}

path: scripts/signChallenge.js
content: const {
  JWSPacker,
  byteEncoder,
  byteDecoder,
  KmsKeyType,
} = require("@0xpolygonid/js-sdk");
const { getInitializedRuntime } = require("./shared/bootstrap");
const {
  parseArgs,
  formatError,
  outputSuccess,
  createDidDocument,
  getAuthResponseMessage,
  buildEthereumAddressFromDid,
} = require("./shared/utils");
const { buildJsonAttestation } = require("./shared/attestation");

async function signChallenge(challenge, entry, kms) {
  const didDocument = createDidDocument(entry.did, entry.publicKeyHex);

  const resolveDIDDocument = {
    resolve: () => Promise.resolve({ didDocument }),
  };

  const jwsPacker = new JWSPacker(kms, resolveDIDDocument);

  challenge.attestationInfo = buildJsonAttestation({
    recipientDid: entry.did,
    recipientEthAddress: buildEthereumAddressFromDid(entry.did),
  });

  const authMessage = getAuthResponseMessage(entry.did, challenge);
  const msgBytes = byteEncoder.encode(JSON.stringify(authMessage));

  let token;
  try {
    token = await jwsPacker.pack(msgBytes, {
      alg: "ES256K-R",
      issuer: entry.did,
      did: entry.did,
      keyType: KmsKeyType.Secp256k1,
    });
  } catch (err) {
    throw new Error(`Failed to sign challenge: ${err.message}`);
  }

  return byteDecoder.decode(token);
}

async function main() {
  try {
    const args = parseArgs();

    if (!args.challenge) {
      console.error("Error: --challenge are required");
      console.error(
        "Usage: node scripts/signChallenge.js --challenge <challenge> [--did <did>]",
      );
      process.exit(1);
    }

    const { kms, didsStorage } = await getInitializedRuntime();

    // Get DID entry - either specific DID or default
    const entry = args.did
      ? await didsStorage.find(args.did)
      : await didsStorage.getDefault();

    if (!entry) {
      const errorMsg = args.did
        ? `No DID ${args.did} found`
        : "No default DID found";
      console.error(errorMsg);
      process.exit(1);
    }

    const challenge = JSON.parse(args.challenge);
    const tokenString = await signChallenge(challenge, entry, kms);

    outputSuccess({ success: true, data: { [REDACTED_SECRET] } });
  } catch (error) {
    console.error(formatError(error));
    process.exit(1);
  }
}

module.exports = { signChallenge };

// Run main if this script is executed directly (not imported as a module)
if (require.main === module) {
  main();
}


path: scripts/verifySignature.js
content: const { JWSPacker, byteEncoder } = require("@0xpolygonid/js-sdk");
const { getInitializedRuntime } = require("./shared/bootstrap");
const { parseArgs, formatError, outputSuccess } = require("./shared/utils");

async function main() {
  try {
    const args = parseArgs();

    if (!args.signature) {
      console.error("Error: --signature parameters is required");
      console.error(
        "Usage: node scripts/verifySignature.js --did <did> --signature <signature>",
      );
      process.exit(1);
    }

    const { kms, challengeStorage } = await getInitializedRuntime();

    // Get the stored challenge
    const challenge = await challengeStorage.getChallenge(args.did);
    if (!challenge) {
      console.error(`Error: No challenge found for DID: ${args.did}`);
      console.error("Generate a challenge first with generateChallenge.js");
      process.exit(1);
    }

    // Create DID resolver that fetches from remote resolver
    const resolveDIDDocument = {
      resolve: async (did) => {
        const resp = await fetch(
          `https://resolver.privado.id/1.0/identifiers/${did}`,
        );
        const didResolutionRes = await resp.json();
        return didResolutionRes;
      },
    };

    // Create JWS packer and unpack signature
    const jws = new JWSPacker(kms, resolveDIDDocument);
    const basicMessage = await jws.unpack(byteEncoder.encode(args.signature));

    // Verify the sender
    if (basicMessage.from !== args.did) {
      console.error(
        `Error: Invalid from: expected from ${args.did}, got ${basicMessage.from}`,
      );
      process.exit(1);
    }

    // Verify the challenge matches
    const payload = basicMessage.body;
    if (payload.message !== challenge) {
      console.error(
        `Error: Invalid signature: challenge mismatch ${payload.message} !== ${challenge}`,
      );
      process.exit(1);
    }

    outputSuccess("Signature verified successfully");
  } catch (error) {
    console.error(formatError(error));
    process.exit(1);
  }
}

main();


path: SECURITY.md
content: # Security Policy

This document describes the security model of the `verified-agent-identity` skill, the threats it does and does not defend against, and the rationale behind design decisions that may surface in automated security scans.

## Scope

`verified-agent-identity` is a **local CLI skill**. It runs on a single operator's host, creates a decentralized identity (DID) for an AI agent, signs challenges with the agent's private key, and persists state under `~/.openclaw/billions/`. It is not a network service, has no listening port, and does not provide multi-tenant trust boundaries.

The only secret it manages is the agent's identity private key, stored in `~/.openclaw/billions/kms.json`.

## Threat Model

**In scope:**

- Preventing the identity key from being accidentally committed into the workspace or read by tools that operate inside the project directory.
- Protecting the key against casual disclosure on a single-user host (e.g. shoulder-surfing, accidental file sharing, careless backups).
- Preventing operator mistakes that would let an identity key double as an asset-holding wallet key.
- Providing opt-in at-rest encryption for shared/multi-user hosts and for environments where compliance requires it.

**Out of scope:**

- An attacker with read access to the operator's home directory or process memory. This is equivalent to full host compromise; no local secret-storage scheme defends against it without an external HSM or OS keystore, and integrating those would expand the dependency surface beyond what this skill commits to.
- Full-disk forensic recovery on a host the attacker physically controls.
- Hostile code already running with the operator's privileges.

## Storage Modes

Private keys are written to `~/.openclaw/billions/kms.json` in one of two formats, selected by the presence of the `BILLIONS_NETWORK_MASTER_KMS_KEY` environment variable.

| `BILLIONS_NETWORK_MASTER_KMS_KEY` | `provider` on disk | `key` value on disk     | Posture                      |
| --------------------------------- | ------------------ | ----------------------- | ---------------------------- |
| Not set                           | `"plain"`          | Raw hex string          | Acceptable on a single-user host with `chmod 700 ~/.openclaw/billions`. |
| Set                               | `"encrypted"`      | `iv:authTag:ciphertext` | **Recommended for all deployments.** AES-256-GCM at rest. |

Mode is selected per-write, so an operator can switch from `plain` to `encrypted` at any time by exporting the variable before the next key creation or import — no migration step is required.

## Compensating Controls

The following mitigations are present in the codebase and the documented installation flow:

- **Out-of-workspace storage.** Keys live under `~/.openclaw/billions/`, never inside the project directory. Tools (and the agent itself) that operate inside the workspace cannot read or exfiltrate them.
- **Filesystem hardening.** The README instructs the operator to run `chmod 700 ~/.openclaw/billions` after the first run (`README.md` → "Key Storage and Isolation").
- **Dedicated-key warning.** The README warns the operator never to import an Ethereum wallet key that holds assets, only a dedicated identity key (`README.md` step 2 warning under the Human CTA).
- **At-rest encryption available behind one env var.** AES-256-GCM is provided via `BILLIONS_NETWORK_MASTER_KMS_KEY`. No code change, no migration, no extra dependency.
- **Versioned on-disk format.** Each `kms.json` entry carries a `version` and `provider` field, so future format upgrades (e.g. an OS-keystore provider) can ship without breaking existing installs. Legacy entries auto-migrate on next write (see `scripts/shared/storage/keys.js`, `_decodeEntry` legacy branch).

## Scanner Findings — Acknowledged Risks

### Identity and Privilege Abuse — `scripts/shared/storage/keys.js` (plaintext storage branch)

**Finding (verbatim):**

> When no master key is configured, the key-storage code writes the raw private key value into `kms.json` as a plaintext entry.
>
> **User impact** — Anyone or any process that can read `~/.openclaw/billions/kms.json` may be able to impersonate the agent identity; if a real asset-holding Ethereum key is imported, the impact could extend beyond the agent identity.
>
> **Recommendation** — Set `BILLIONS_NETWORK_MASTER_KMS_KEY` before creating or importing keys, use only a dedicated no-assets identity key, restrict `~/.openclaw/billions` permissions, and avoid importing any wallet key that controls funds.

**Status: acknowledged, accepted — every item in the scanner's recommendation is already a documented and shipped control.**

The flagged code path is the documented `provider: "plain"` mode (see [Storage Modes](#storage-modes)). It is the default **only because the env var is unset**; setting `BILLIONS_NETWORK_MASTER_KMS_KEY` switches the same code path to AES-256-GCM with no further operator action. The threat the plaintext mode enables — local read of `~/.openclaw/billions/kms.json` on the operator's own host — is out of scope per the [Threat Model](#threat-model) above: an attacker with that level of access already controls the operator's shell history, SSH agent, browser secrets, and process memory.

#### Recommendation-to-Control mapping

| Scanner recommendation | Control in this repository | Reference |
| --- | --- | --- |
| Set `BILLIONS_NETWORK_MASTER_KMS_KEY` before creating or importing keys | A `> Note` block immediately precedes every key-creation command in the README, instructing the operator to set the variable. The `KMS Encryption` section documents the on-disk format change and the AES-256-GCM scheme. | `README.md` → "KMS Encryption" |
| Use only a dedicated, no-assets identity key | An explicit `> Warning` block under the key-creation step tells the operator never to pass an asset-holding wallet key to `--key`. | `README.md` step 2 of "Human CTA" |
| Restrict `~/.openclaw/billions` permissions | The "Key Storage and Isolation" section instructs `chmod 700 ~/.openclaw/billions` after the first run. The directory itself sits **outside the agent workspace**, so workspace-scoped tools cannot read it. | `README.md` → "Key Storage and Isolation" |
| Avoid importing any wallet key that controls funds | Same `> Warning` block as above; reinforced in the [Operator Checklist](#operator-checklist) below. | `README.md` step 2 warning + this document |

#### Why the plaintext mode is retained

1. **Zero-config local development and CI smoke tests** — no master secret to fetch or commit.
2. **Backward compatibility** — existing `kms.json` files written by earlier versions of the skill remain readable; legacy entries auto-migrate on the next write (`scripts/shared/storage/keys.js` → `_decodeEntry` legacy branch).
3. **Single code path** — the same write path becomes encrypted at rest the moment `BILLIONS_NETWORK_MASTER_KMS_KEY` is set. There is no separate "secure mode" the operator has to migrate to, so the plaintext default cannot drift away from the encrypted path over time.

The [Operator Checklist](#operator-checklist) is the recommended deployment posture and exactly matches the scanner's recommendation.

## Operator Checklist

1. **Set the master key first.**
   ```bash
   export BILLIONS_NETWORK_MASTER_KMS_KEY="<a strong secret>"
   ```
   Do this **before** the first `node scripts/createNewEthereumIdentity.js`. Keys created without it are written as `provider: "plain"`.
2. **Use a dedicated identity key.** Never reuse an Ethereum private key that holds assets. If the `kms.json` file is exposed, every key inside it should be revocable / disposable.
3. **Restrict the storage directory.**
   ```bash
   chmod 700 ~/.openclaw/billions
   ```
4. **Back up the master key out of band.** If `BILLIONS_NETWORK_MASTER_KMS_KEY` is lost, every entry written under `provider: "encrypted"` is unrecoverable.

## Reporting a Vulnerability

Please report suspected vulnerabilities privately to the Billions Network security contact rather than filing a public issue. Open an issue marked `security` requesting a private disclosure channel if you do not already have one.


path: README.md
content: # Verified Agent Identity

A decentralized identity management toolkit for AI agents using iden3 protocol on Billions Network.

## Overview

This skill enables AI agents to create, manage, link, prove and verify ownership of decentralized identities (DIDs) using cryptographic signatures.

## Installation

### Agent CTA:

1. Ask bot to install the skill:

   Install with clawhub:

   ```plaintext
   Install the skill `npx clawhub@latest install verified-agent-identity`
   ```

   Or install with skills.sh:

   ```plaintext
   Intall the skill `npx skills add BillionsNetwork/verified-agent-identity`
   ```

   Or

   ```plaintext
   Install the `verified-agent-identity` skill from the OpenClaw clawhub.ai.
   ```

2. (Optional) If the verification process did not start automatically after installation, ask your bot to initialize the process by sending a message like:

   ```plaintext
   Please link your agent identity to me.
   ```

### Human CTA:

1. Install the skill:

   Use clawhub to install the skill:

   ```bash
   npx clawhub@latest install verified-agent-identity
   ```

   Use skills.sh to install the skill:

   ```bash
   npx skills add BillionsNetwork/verified-agent-identity
   ```

2. Create a new identity:

   ```bash
   # Generate a new key and create a new identity
   node scripts/createNewEthereumIdentity.js
   ```

   Or

   ```bash
   # Use an existing private key to create an identity
   BILLIONS_NETWORK_MASTER_KMS_KEY="<your-strong-secret>" node scripts/createNewEthereumIdentity.js --key <your-ethereum-private-key>
   ```

   > **Warning**: Only pass a **dedicated identity key** to `--key` — never an Ethereum wallet key that holds assets. If the key file is exposed, any key stored here could be used to impersonate the agent or, if reused, to control the associated wallet.

3. Generate a verification link to connect your human identity to the agent:

   ```bash
   node scripts/manualLinkHumanToAgent.js --challenge '{"name": "Agent Name", "description": "Short description of the agent"}'
   ```

   This prints the verification URL to the console. Open it in your browser to complete the identity linking process.

## Features

- **Identity Creation**: Generate new DIDs with random or existing Ethereum private keys
- **Identity Management**: List and manage multiple identities with default identity support
- **Human-Agent Linking**: Link a human identity to an agent's DID through signed challenges
- **Proof Generation**: Generate cryptographic proofs to authenticate as a specific identity
- **Proof Verification**: Verify proofs to confirm identity ownership

## Architecture

### Runtime Requirements

- **Node.js `>= v20`** and **npm** are required to run the scripts.

### Dependency Surface

npm dependencies are intentionally minimal and scoped to well-established, audited packages:

| Package                | Purpose                                                      |
| ---------------------- | ------------------------------------------------------------ |
| `@0xpolygonid/js-sdk`  | iden3/Privado ID cryptographic primitives and key management |
| `@iden3/js-iden3-core` | DID and identity core types                                  |
| `@iden3/js-iden3-auth` | JWS/JWA authorization response construction and verification |
| `ethers`               | Ethereum key utilities                                       |
| `uuid`                 | UUID generation for protocol message IDs                     |

Core libraries governing identity management use pinned, well-tested versions to ensure stability and security.

### Key Storage and Isolation

All cryptographic material is persisted to `$HOME/.openclaw/billions/` — a directory that lives **outside the agent's workspace**:

| File               | Contents                                                                           |
| ------------------ | ---------------------------------------------------------------------------------- |
| `kms.json`         | Private keys — per-entry versioned format; keys are plain or AES-256-GCM encrypted |
| `identities.json`  | Identity metadata                                                                  |
| `defaultDid.json`  | Active DID and associated public key                                               |
| `challenges.json`  | Per-DID challenge history                                                          |
| `credentials.json` | Verifiable credentials                                                             |

After the first run, restrict access to this directory: `chmod 700 ~/.openclaw/billions`

There are several ways of storing private keys, to enable master key encryption as described in the **KMS Encryption** section below.

### KMS Encryption

> See [SECURITY.md](SECURITY.md) for the full threat model, the rationale for shipping a plaintext storage mode, and the operator hardening checklist.

Set the environment variable `BILLIONS_NETWORK_MASTER_KMS_KEY` to enable AES-256-GCM at-rest encryption for the private keys inside `kms.json`. When set, every key value is individually encrypted on write; when absent, keys are stored as plain hex strings.

**`kms.json` entry format**

Each entry in the array is versioned. The `alias` is always stored in plaintext — only the `key` value is encrypted:

```json
[
  {
    "version": 1,
    "provider": "plain",
    "data": {
      "alias": "secp256k1:abc123",
      "key": "deadbeef...",
      "createdAt": "2026-03-12T13:46:04.094Z"
    }
  },
  {
    "version": 1,
    "provider": "encrypted",
    "data": {
      "alias": "secp256k1:xyz456",
      "key": "<iv_hex>:<authTag_hex>:<ciphertext_hex>",
      "createdAt": "2026-02-11T13:00:02.032Z"
    }
  }
]
```

**Behavior summary**

| `BILLIONS_NETWORK_MASTER_KMS_KEY` | `provider` on disk | `key` value on disk     |
| --------------------------------- | ------------------ | ----------------------- |
| Not set                           | `"plain"`          | Raw hex string          |
| Set                               | `"encrypted"`      | `iv:authTag:ciphertext` |

> **Backward compatibility** — the legacy format `[ { "alias": "...", "privateKeyHex": "..." } ]` is still read correctly. On the first write the file is automatically migrated to the new per-entry format. No manual step is required.

**How to set the variable**

_Option 1 — openclaw skill config (recommended for agent deployments):_

Add an `env` block for the skill inside your openclaw config:

```json
"skills": {
  "entries": {
    "verified-agent-identity": {
      "env": {
        "BILLIONS_NETWORK_MASTER_KMS_KEY": "<your-strong-secret>"
      }
    }
  }
}
```

_Option 2 — shell or process environment:_

```bash
export BILLIONS_NETWORK_MASTER_KMS_KEY="<your-strong-secret>"
node scripts/createNewEthereumIdentity.js
node scripts/manualLinkHumanToAgent.js --challenge '{"name": "Agent Name", "description": "Short description of the agent"}'
```

For all other ways to pass environment variables to a skill see the [OpenClaw environment documentation](https://docs.openclaw.ai/help/environment).

**CRITICAL**: Save master keys securely and do not share them. If the master key is lost, all encrypted keys will be lost.

### Network and External Binary Policy

- All external https calls will be made to trusted resources. Signed JWS attestation (proof of agent ownership) is encoded securely by utilizing robust security practices. It requires an explicit user consent to pass it to any other source.
- All network calls are directed to legitimate DID resolvers (resolver.privado.id) or the project's own infrastructure (billions.network). These network calls cannot exfiltrate signed attestations or identity data to other third-party services by skill design. Wallet interaction is possible only through explicit action from the user side with consent. Also attestation contains only publicly verifiable information.
- Whitelisted domains:
  - `resolver.privado.id` (DID resolution)
  - `billions.network` (Billions Network interactions)

## Documentation

See [SKILL.md](SKILL.md) for detailed usage instructions and examples.


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)