@parallelmarkets/token

0.0.2 • Public • Published

Parallel Markets Identity (PID) Token

The Parallel Identity (PID) Token is a non-transferrable, non-fungible token (NFT) that links real world individual and business identities with Ethereum wallet addresses. The PID Token provides accreditation, Know Your Customer (KYC), and international sanctions information in the form of a ERC-721 compatible token.

The PID Token has a number of features:

  1. Parallel Markets provides ongoing sanctions monitoring information on-chain for every PID Token holder for a year after minting
  2. Individuals (natural persons) and businesess (any form of corporate entity) can have a PID Token
  3. Tokens can contain additional traits, including accreditation status and other DeFi-related information
  4. While no PII is stored in the Token, every Token holder has gone through a rigorous KYC process, including for any business/corporate entity that owns the wallet

See our Developer Docs for more information.

Getting Started

You can access PID Token information either directly on-chain on the Ethereum Mainnet or via one of the Web3 JavaScript libraries.

Ethereum Contract Access

Here's a quick example example of usage on-chain to determine if a Token holder (individual or business) is currently accredited and free from sanctions.

import "@parallelmarkets/token/contracts/IParallelID.sol";

contract MyContract {
    // This is the address on Mainnet. For testing in the sandbox environment, use the
    // Rinkeby contract at 0x0F2255E8aD232c5740879e3B495EA858D93C3016
    address PID_CONTRACT = "0x9ec6232742b6068ce733645AF16BA277Fa412B0A";

    function isSanctionsSafe(address subject) returns (bool) {
        // Get a handle for the Parallel Identity Token contract
        IParallelID pid = IParallelID(PID_CONTRACT);

        // It's possible a subject could have multiple tokens issued over time - check
        // to see if any are currently monitored and safe from sanctions
        for (uint256 i = 0; i < pid.balanceOf(subject); i++) {
            uint256 tokenId = pid.tokenOfOwnerByIndex(subject, i);
            if (pid.isSanctionsSafe(tokenId)) return true;
        }
        return false;
    }

    function currentlyAccredited(address subject) returns (bool) {
        // Get a handle for the Parallel Identity Token contract
        IParallelID pid = IParallelID(PID_CONTRACT);

        // It's possible a subject could have multiple tokens issued over time - check
        // to see if any have an "accredited" trait and were minted in the last 90 days
        // (US regulation says accreditation certification only lasts 90 days)
        for (uint256 i = 0; i < pid.balanceOf(subject); i++) {
            uint256 tokenId = pid.tokenOfOwnerByIndex(subject, i);
            bool recent = pid.mintedAt(tokenId) >= block.timestamp - 90 days;
            bool accredited = pid.hasTrait(tokenId, "accredited");
            if (recent && accredited) return true;
        }
        return false;
    }
}

dApp JavaScript Access

This example uses the ethers.js library.

import { utils, Contract } from 'ethers'

const abi = [
  "function tokenOfOwnerByIndex(address owner, uint256 index) view returns (uint256)",
  "function balanceOf(address owner) view returns (uint256 balance)",
  "function hasTrait(uint256 tokenId, string memory trait) view returns (bool)",
  "function isSanctionsSafe(uint256 tokenId) view returns (bool)"
]

// Address on the Rinkeby test network
const PID_CONTRACT = "0x6737fAA302d607e0e3B06C51E3b5D28c5624F96A"
const contract = new Contract(PID_CONTRACT, abi, provider)

const isSanctionsSafe = (address) => {
  for (let i = 0; i < contract.balanceOf(address); i++) {
    const tokenId = contract.tokenOfOwnerByIndex(address, i)
    if (contract.isSanctionsSafe(tokenId)) return true
  }
  return false
}

const currentlyAccredited = (address) => {
  const ninetyDaysAgo = ((new Date()).getTime() / 1000) - (90 * 86400)
  for (let i = 0; i < contract.balanceOf(address); i++) {
    const tokenId = contract.tokenOfOwnerByIndex(address, i)
    const recent = contract.mintedAt(tokenId) >= ninetyDaysAgo
    const accredited = contract.hasTrait(tokenId, "accredited")
    if (recent && accredited) return true
  }
  return false
}

Development

We use Hardhat for contract building / testing.

Setup / Installation

Just run:

> pnpm i

Testing

This will run all tests / linters:

> pnpm test

Gas Estimates

Use this to see what current costs are for contract calls:

> OPTIMIZE=true REPORT_GAS=true pnpm exec hardhat test

Deployment

Ensure the network you'd like to deploy to is configured in hardhat.config.js, then run:

> OPTIMIZE=true pnpm exec hardhat run --network <network name> scripts/deploy.js

Issuing Tokens

Edit the scripts/mint.js file with the address of the contract and token recipient, then run:

> pnpm exec hardhat run --network <network name> scripts/mint.js

Note - this is just for testing; production token minting is done via the recipientMint function.

Etherscan verification

After deploying, run:

pnpm exec hardhat verify --network <network name> <contract address>

This will verify the contract on Etherscan (so everyone can see the source code).

Package Sidebar

Install

npm i @parallelmarkets/token

Weekly Downloads

1

Version

0.0.2

License

MIT

Unpacked Size

26.5 kB

Total Files

7

Last publish

Collaborators

  • rickdt
  • bmuller