# Integrating hPassport into Your hApp

### 1. Retrieve User Attributes from hPassport

When a user interacts with your hApp, you can retrieve various attributes from their **hPassport** to verify identity or personalize the experience.

**Example: Retrieve the User's Primary Identity**

```solidity
solidityCopy code// Retrieve the user’s primary identity
(bool primaryID, uint256 expiry, uint256 updatedAt) = proofOfIdentity.getPrimaryID(userAddress);

// Ensure the user is verified
require(primaryID, "User is not verified.");
```

**Example: Retrieve the User's Country of Residence Code**

```solidity
solidityCopy code// Retrieve the user’s country code
(string memory countryCode, uint256 expiry, uint256 updatedAt) = proofOfIdentity.getCountryCode(userAddress);
```

### 2. Enforcing Identity Verification in Smart Contracts

To ensure only verified users can interact with your contract, check their hPassport before executing any logic. Here's how you can implement this in your contract:

```solidity
solidityCopy codepragma solidity ^0.8.0;

import { IProofOfIdentity } from "./IProofOfIdentity.sol";

contract VerifiedAuction {

    IProofOfIdentity proofOfIdentity;

    constructor(address _proofOfIdentity) {
        proofOfIdentity = IProofOfIdentity(_proofOfIdentity);
    }

    modifier onlyVerified(address user) {
        (bool primaryID,,) = proofOfIdentity.getPrimaryID(user);
        require(primaryID, "User is not verified.");
        _;
    }

    function placeBid() external onlyVerified(msg.sender) {
        // auction logic here
    }
}
```

### 3. Personalizing User Experiences Based on hPassport Attributes

You can personalize the experience for users based on the anonymized data available on their **hPassport**. For example, you can restrict certain features based on a user's county of residence, or other attributes.

**Example: Regional Restriction**

```solidity
solidityCopy code// Retrieve the user’s country code
(string memory countryCode,,) = proofOfIdentity.getCountryCode(userAddress);

// Check if the user is from an allowed country
require(keccak256(abi.encodePacked(countryCode)) == keccak256(abi.encodePacked("US")), "Service not available in your country.");
```

### 4. Handling Suspended Users

To prevent suspended users from interacting with your hApp, you can check the suspension status of the user's hPassport:

```solidity
solidityCopy code// Check if user account is suspended
bool isSuspended = proofOfIdentity.isSuspended(userAddress);
require(!isSuspended, "User account is suspended.");
```

### 5. Multiple Account Support

hPassport allows verified users to have multiple wallets, linking their identity to both a primary account and auxiliary accounts. You can retrieve the auxiliary accounts linked to a user’s hPassport as follows:

```solidity
solidityCopy code// Retrieve auxiliary accounts linked to a principal account
address[] memory auxAccounts = proofOfIdentity.auxiliaryAccounts(principalAddress);
```

***

## hPassport API Reference

Below are the key functions available in the **hPassport** contract:

#### Identity Verification Functions

* **getPrimaryID(address account)**: Returns a boolean indicating if the user is verified, along with the expiration and last update timestamp.

  ```solidity
  solidityCopy code(bool primaryID, uint256 expiry, uint256 updatedAt) = proofOfIdentity.getPrimaryID(userAddress);
  ```
* **getCountryCode(address account)**: Retrieves the user’s country code (stored as a string).

  ```solidity
  solidityCopy code(string memory countryCode, uint256 expiry, uint256 updatedAt) = proofOfIdentity.getCountryCode(userAddress);
  ```
* **getProofOfLiveliness(address account)**: Retrieves whether the user has passed proof of liveliness checks.

  ```solidity
  solidityCopy code(bool liveliness, uint256 expiry, uint256 updatedAt) = proofOfIdentity.getProofOfLiveliness(userAddress);
  ```
* **getUserType(address account)**: Retrieves the type of user (e.g., retail, institution).

  ```solidity
  solidityCopy code(uint256 userType, uint256 expiry, uint256 updatedAt) = proofOfIdentity.getUserType(userAddress);
  ```
* **isSuspended(address account)**: Checks if the user’s hPassport is suspended.

  ```solidity
  solidityCopy codebool suspended = proofOfIdentity.isSuspended(userAddress);
  ```

#### Auxiliary Account Functions

* **auxiliaryAccounts(address principal)**: Returns auxiliary accounts linked to the principal account.

  ```solidity
  solidityCopy codeaddress[] memory auxAccounts = proofOfIdentity.auxiliaryAccounts(principalAddress);
  ```

***

### Example Use Case: Auction with Verified Users

This example demonstrates how to build an auction application that only allows verified users to participate. The auction uses hPassport to ensure that only users with a verified identity can place bids.  This directory contains this example contract

[**AuctionPOI.sol**](https://github.com/haven1network/proof-of-identity-hackathon/blob/main/contracts/proof-of-identity/examples/AuctionPOI.sol): This contract is an implementation of an NFT auction system. It uses the `userType` of an account to permission the auction process, showcasing how user identity attributes can govern smart contract functionalities.

```solidity
solidityCopy codepragma solidity ^0.8.0;

import { IProofOfIdentity } from "./IProofOfIdentity.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";

contract VerifiedAuction is ReentrancyGuardUpgradeable {

    IProofOfIdentity proofOfIdentity;
    IERC721Upgradeable nft;
    address highestBidder;
    uint256 highestBid;
    uint256 auctionEndTime;

    constructor(address _proofOfIdentity, address _nft) {
        proofOfIdentity = IProofOfIdentity(_proofOfIdentity);
        nft = IERC721Upgradeable(_nft);
    }

    modifier onlyVerified(address user) {
        (bool primaryID,,) = proofOfIdentity.getPrimaryID(user);
        require(primaryID, "User is not verified.");
        _;
    }

    function placeBid() external payable onlyVerified(msg.sender) {
        require(msg.value > highestBid, "Bid too low.");
        require(block.timestamp < auctionEndTime, "Auction has ended.");

        // Refund the previous highest bidder
        if (highestBidder != address(0)) {
            payable(highestBidder).transfer(highestBid);
        }

        highestBid = msg.value;
        highestBidder = msg.sender;
    }

    function endAuction() external {
        require(block.timestamp >= auctionEndTime, "Auction not ended.");
        nft.transferFrom(address(this), highestBidder, 1);
    }
}
```

#### Important Notes

* **Demonstration Purpose**: These contracts incorporate many Solidity best practices but are intended for demonstration purposes only.
* **Production Considerations**:
  * The `bid` function in `AuctionPOI.sol` (line 280) should include a reentrancy guard in a production environment.
  * The transfer of H1 tokens in `AuctionPOI.sol` (lines 454 and 468) should be approached with caution, avoiding optimistic transfers in most cases.

#### Identity Verification Checks

Both contracts include explicit checks for:

* The presence of an account’s ID NFT.
* The suspended status of the account.

In the Haven1 network, these checks would typically be redundant as the network itself restricts transactions for accounts without an ID NFT or with a suspended status. However, they are included in these examples for educational purposes.

#### Testing

Example tests for both contracts are available in the directory: `test/proof-of-identity/examples`. These tests can be used as a reference for developing and validating your own contracts that interact with the hPassport.
