Skip to content
    hazBasehazBaseDocs
    IMPLEMENTATION PATTERNS

    Access & membership

    Manage rights to use facilities or services and participation conditions.

    All implementation patterns
    EXAMPLE

    Issue facility passes and verify access at reception

    Issue one facility pass to a member, then verify wallet ownership and holdings at reception. One PrivilegeEdition ID represents passes with shared terms, making it suitable for members with the same access period.

    Connect enrollment, issuance, access decisions and visit history. Monthly passes and single-use tickets use different consumption workflows.

    Architecture and responsibilities

    1. Member interface

      Handle sign-in and proof of wallet ownership.

      Authentication / Wallet linking
    2. Membership and facility rules

      Store facilities, validity periods, suspensions and pass IDs.

      Application DB
    3. Pass issuance and consumption

      Manage holdings, issuance and transfer rules per ID.

      PrivilegeEditionHelper / ERC-1155
    4. Reception and visit history

      Check eligibility and facility rules, then record admission under a visit ID.

      Reception API / Visit records

    Example data model

    Map application records to the data managed by the chain or APIs. Field names and values below illustrate the application model for this architecture.

    Field and exampleStored inPurpose and mapping
    memberId / walletAddressMEM-001 / 0x…Application DBLink the member ID to an address verified by signature or wallet linking.
    facilityId / editionIdLAB-TOKYO / 20270901Application DBMap the facility to an ID representing passes with shared terms.
    chainId / editionAddresschainId / 0x…DB and chainIdentify the PrivilegeEdition contract issuing the passes.
    expiresAt / tierUNIX seconds / 0Chain and issuance settingstier is zero here. It controls voting weight, not an access rank. Expiry and other terms are shared per ID.
    balance1ChainRead using ERC-1155 balanceOf(member, editionId).
    visitId / statusVISIT-001 / admittedApplication DBManage duplicate admissions, concurrent use and single-use ticket consumption.

    Processing flow

    1. Configure the pass type

      Assign an ID to a facility, validity period and transfer policy. URI, expiry and tier are shared from the first issuance of an ID, so use different IDs for different periods.

      PrivilegeEditionHelper.attach / soulbound
    2. Issue to the verified member wallet

      Complete enrollment and wallet ownership verification, then mint one pass. Keep names and contact details in the application DB and publish only suitable facility and terms metadata.

      mint(member, editionId, 1n, uri, 0, expiresAt, 0n)
    3. Check access at reception

      Verify the member with a short-lived challenge, then check balance, validity against server time, facility coverage and suspension status. An entered address or balance alone does not authorize access.

      Wallet ownership check → contract.balanceOf → application access rules
    4. Record or consume the pass

      For a monthly pass, record the visit without reducing the balance. For a single-use ticket, redeem with the holder’s or an approved operator’s signer and record admission after confirmation.

      Monthly: visit record / Single-use: redeem(holder, editionId, 1n)
    5. Handle renewals and expiry

      Issue a new period’s ID on renewal. Reject expired passes even if their balance remains, and use sweepExpired when cleanup is needed. Apply membership suspensions in the reception rules.

      New editionId / sweepExpired / application suspension state

    Before using the code

    • Initialize PrivilegeEdition and grant the issuer MINTER_ROLE. Check the soulbound setting for non-transferable membership passes.
    • Save editionId, URI and expiry as issuance settings. Do not use a later mint with different terms to update an existing ID.
    • Pass expiresAt in UNIX seconds. Evaluate access using trusted member and facility settings and server time.
    Install
    npm install --save-exact @hazbase/kit@0.9.0 ethers@6.16.0

    The TypeScript functions below are called from your application with the appropriate connections, permissions and data. Integrate the UI, persistence and recovery using the architecture above.

    Issue a pass or consume a single-use ticket

    issueFacilityPass uses the issuer’s signer. consumeFacilityPass is for single-use tickets and uses the holder’s signer; do not call it for monthly-pass admissions.

    pattern-access.ts
    import { PrivilegeEditionHelper } from '@hazbase/kit';
    type Signer = Parameters<typeof PrivilegeEditionHelper.deploy>[1];
    
    export async function issueFacilityPass(input: {
      editionAddress: string;
      member: string;
      editionId: bigint;
      metadataUri: string;
      expiresAt: bigint;
      issuer: Signer;
    }) {
      // One edition ID shares one URI, expiry and tier across all holders.
      const pass = PrivilegeEditionHelper.attach(input.editionAddress, input.issuer);
      const receipt = await pass.mint(
        input.member, input.editionId, 1n,
        input.metadataUri, 0, input.expiresAt, 0n,
      );
      // Standard ERC-1155 balanceOf is available on the underlying contract.
      const balance = BigInt(await pass.contract.balanceOf(input.member, input.editionId));
      return { balance: balance.toString(), transactionHash: receipt.hash };
    }
    
    export async function consumeFacilityPass(
      editionAddress: string,
      editionId: bigint,
      holder: Signer,
    ) {
      // Use for a single-use pass, after the service checks its validity.
      const pass = PrivilegeEditionHelper.attach(editionAddress, holder);
      const receipt = await pass.redeem(await holder.getAddress(), editionId, 1n);
      return { transactionHash: receipt.hash, blockNumber: receipt.blockNumber };
    }
    
    Download the example

    Result and application integration

    After issuance to a new member, the ID balance becomes one. Redeeming a ticket reduces the balance and emits RewardRedeemed. The reception system handles actual admission or service delivery.

    Implementation considerations

    Check balance and validity separately

    Expired passes may retain a balance before cleanup. Combine a positive balance with expiry, suspension and facility checks.

    Duplicate admissions

    Make visitId unique and distinguish pending admission, submitted consumption, confirmation and admission. Recover the existing visit state after a connection failure.

    Individual validity periods

    An edition ID has one shared expiry. For individual periods such as 30 days from enrollment, use separate IDs or a different credential model.

    Extending the architecture

    Operator-assisted reception

    An approved operator can consume tickets under an appropriate authorization design. Scanning a QR code alone does not grant control of a member’s assets.

    Conditional distribution

    Manage eligibility with Whitelist. For vouchers, combine distribution with signed issuer, recipient, expiry and replay-protection nonce conditions.