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:
- Parallel Markets provides ongoing sanctions monitoring information on-chain for every PID Token holder for a year after minting
- Individuals (natural persons) and businesess (any form of corporate entity) can have a PID Token
- Tokens can contain additional traits, including accreditation status and other DeFi-related information
- 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.
You can access PID Token information either directly on-chain on the Ethereum Mainnet or via one of the Web3 JavaScript libraries.
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 {
// 0x9ec6... is the address on Mainnet. For testing in the sandbox environment,
// use the Goerli contract at 0x0F2255E8aD232c5740879e3B495EA858D93C3016
address public PID_CONTRACT = 0x9ec6232742b6068ce733645AF16BA277Fa412B0A;
function isSanctionsSafe(address subject) public view 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) public view 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;
}
}
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)"
]
// 0x9ec6... is the address on Mainnet. For testing in the sandbox environment,
// use the Goerli contract at 0x0F2255E8aD232c5740879e3B495EA858D93C3016
const PID_CONTRACT = "0x9ec6232742b6068ce733645AF16BA277Fa412B0A"
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
}
We use Hardhat for contract building / testing.
Just run:
> pnpm i
This will run all tests / linters:
> pnpm test
Use this to see what current costs are for contract calls:
> OPTIMIZE=true REPORT_GAS=true pnpm exec hardhat test
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
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.
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).