Skip to content

Commit

Permalink
docs: update readme v4
Browse files Browse the repository at this point in the history
  • Loading branch information
superical committed Apr 2, 2024
1 parent a953def commit 6dc0eac
Show file tree
Hide file tree
Showing 2 changed files with 224 additions and 76 deletions.
300 changes: 224 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,128 +1,276 @@
# Document Store
<h1 align="center">
<p align="center">Document Store</p>
<img src="https://github.com/Open-Attestation/document-store/blob/beta/docs/images/document-store-banner.png?raw=true" alt="OpenAttestation Document Store" />
</h1>

The [Document Store](https://github.com/Open-Attestation/document-store) repository contains the following:
<p align="center">
Document Store Smart Contracts for the <a href="https://www.openattestation.com">OpenAttestation</a> framework
</p>

- The smart contract code for document store in the `/contracts` folder
- The node package for using this library in the `/src` folder
<p align="center">
<a href="https://github.com/Open-Attestation/document-store/actions" alt="Build Status"><img src="https://github.com/Open-Attestation/document-store/actions/workflows/release.yml/badge.svg" /></a>
<a href="https://codecov.io/gh/Open-Attestation/document-store" alt="Code Coverage"><img src="https://codecov.io/gh/Open-Attestation/document-store/branch/beta/graph/badge.svg?token=Y4R9SWXATG" /></a>
<a href="https://github.com/Open-Attestation/document-store/blob/master/LICENSE" alt="License"><img src="https://img.shields.io/badge/License-Apache_2.0-blue.svg" /></a>
</p>

The Document Store is a set of smart contracts for managing the issuance and revocation of documents. It is designed to be used in conjunction with the [OpenAttestation](https://github.com/Open-Attestation/open-attestation) library to issue and verify documents on the blockchains.

There are 2 types of document stores, namely, the regular _Document Store_ and the _Transferable Document Store_.

#### Document Store

The regular _Document Store_ allows issuers to issue and revoke documents. However, these documents do not have an owner and are, hence, not transferable. Multiple documents issued on the Document Store can be "batched" under a single hash for issuance.

#### Transferable Document Store

The _Transferable Document Store_ allows issuers to issue and revoke documents, and these documents have an owner and are transferable. Each document is essentially an ERC-721 NFT (Non-Fungible Token). Thus, documents are issued individually and the document holder's identity can be verified. Although the documents are transferable, they can also be issued as "soulbound" documents which bounds to an owner. This can be particularly useful for certain use cases such as POAP.

---

## Table of Contents

- [Installation](#installation)
- [Usage](#usage)
- [Document Store](#document-store-1)
- [Transferable Document Store](#transferable-document-store-1)
- [Roles and Access](#roles-and-access)
- [Deployment](#deployment)
- [Document Store](#document-store-2)
- [Transferable Document Store](#transferable-document-store-2)
- [Hardware Wallet](#hardware-wallet)
- [Verification](#verification)
- [Supported Networks](#supported-networks)
- [Configuration](#configuration)
- [Development](#development)
- [Additional Information](#additional-information)

---

## Installation

To install OpenAttestation document store on your machine, run the command below:
To make integration easier, we have provided the packages containing the Typechain bindings for interacting with the document store.

#### Using with ethers.js v6

```sh
npm i @govtechsg/document-store
npm install @govtechsg/document-store-ethers-v6
```

---
#### Using with ethers.js v5

```sh
npm install @govtechsg/document-store-ethers-v5
```

## Usage

Provide one of the following depending on your needs:
### Document Store

For a complete list of functions, refer to [IDocumentStoreBatchable.sol](src/interfaces/IDocumentStoreBatchable.sol).

- To use the package, provide your own Web3 [provider](https://docs.ethers.io/v5/api/providers/api-providers/).
#### Issuing a document:

- To write to the blockchain, provide the [signer](https://docs.ethers.io/v5/api/signer/#Wallet) instead.
```typescript
import { DocumentStore__factory } from "@govtechsg/document-store-ethers-v6"; // Or from "@govtechsg/document-store-ethers-v5"

### Deploying a new document store
const documentStore = DocumentStore__factory.connect(documentStoreAddress, signer);
const tx = await documentStore["issue"]("0x1234");
await tx.wait();
```

The following shows a code example to deploy a new document store:
#### Checking if a document in a batch is issued:

```ts
import { deployAndWait } from "@govtechsg/document-store";
```typescript
const oaDocumentSignature = {
documentRoot: "0xMerkleRoot",
targetHash: "0xTargetHash",
proof: ["0xProof1", "0xProof2"]
};

const documentStore = await deployAndWait("My Document Store", signer).then(console.log);
const documentStore = DocumentStore__factory.connect(documentStoreAddress, signer);
const tx = await documentStore["issue"](oaDocumentSignature.documentRoot);
await tx.wait();

try {
const isDocIssued = await documentStore.isIssued(
oaDocumentSignature.documentRoot,
oaDocumentSignature.targetHash,
oaDocumentSignature.proof
);

console.log(isDocIssued); // Returns true or false
} catch (e) {
// Error will be thrown if proof is invalid
console.error(e);
}
```

### Connecting to an existing document store
#### Bulk issuing documents:

The following shows a code example to connect to an existing document store:
Note that this is different from batching. This issues multiple documents or document roots at once.

```ts
import { connect } from "@govtechsg/document-store";
```typescript
const documentStore = DocumentStore__factory.connect(documentStoreAddress, signer);
const bulkIssuances = [
documentStore.interface.encodeFunctionData("issue", ["0xDocRoot1"]),
documentStore.interface.encodeFunctionData("issue", ["0xDocRoot2"])
];
const tx = await documentStore.multicall(bulkIssuances);
await tx.wait();
```

const documentStore = await connect("0x4077534e82c97be03a07fb10f5c853d2bc7161fb", providerOrSigner);
#### Revoking a document root:

```typescript
const documentStore = DocumentStore__factory.connect(documentStoreAddress, signer);
const tx = await documentStore["revoke"]("0x1234");
await tx.wait();
```

### Interacting with a document store
#### Revoking a document in a batch:

The following shows a code example to interact with a document store:
```typescript
const documentStore = DocumentStore__factory.connect(documentStoreAddress, signer);
const tx = await documentStore["revoke"]("0xDocumentRoot", "0xTargetHash", ["0xProof1", "0xProof2"]);
await tx.wait();
```

```ts
const issueMerkleRoot = async () => {
const documentStore = connect("0x4077534e82c97be03a07fb10f5c853d2bc7161fb", signer);
### Transferable Document Store

const tx = await documentStore.issue("0x7fe0b58ed760804eb7118988637693c4351613be327b56527e55bcd0a8d170d7");
const receipt = await tx.wait();
console.log(receipt);
For a complete list of functions, refer to [ITransferableDocumentStore.sol](src/interfaces/ITransferableDocumentStore.sol).

const isIssued = await instance.isIssued("0x7fe0b58ed760804eb7118988637693c4351613be327b56527e55bcd0a8d170d7");
console.log(isIssued);
};
#### Issuing a transferable document:

```typescript
import { TransferableDocumentStore__factory } from "@govtechsg/document-store-ethers-v6"; // Or from "@govtechsg/document-store-ethers-v5"

const transferableDocumentStore = TransferableDocumentStore__factory.connect(transferableDocumentStoreAddress, signer);

// Issues a transferable document
const tx = await transferableDocumentStore.issue("0xRecipientAddress", "0xDocTargetHash", false);
await tx.wait();

//Issues a soulbound document
const tx = await transferableDocumentStore.issue("0xRecipientAddress", "0xDocTargetHash", true);
await tx.wait();
```

### List of available functions
#### Revoke a transferable document

```typescript
const transferableDocumentStore = TransferableDocumentStore__factory.connect(transferableDocumentStoreAddress, signer);
const tx = await transferableDocumentStore.revoke("0xDocTargetHash");
await tx.wait();
```

### Roles and Access

Roles are useful for granting users to access certain functions only. Here are the designated roles meant for the different key operations.

The following is a list of available functions to be used with document store:
| Role | Access |
| -------------------- | ------------------------------ |
| `DEFAULT_ADMIN_ROLE` | Able to perform all operations |
| `ISSUER_ROLE` | Able to issue documents |
| `REVOKER_ROLE` | Able to revoke documents |

- `documentIssued`
- `documentRevoked`
- `isOwner`
- `name`
- `owner`
- `renounceOwnership`
- `transferOwnership`
- `version`
- `initialize`
- `issue`
- `bulkIssue`
- `getIssuedBlock`
- `isIssued`
- `isIssuedBefore`
- `revoke`
- `bulkRevoke`
- `isRevoked`
- `isRevokedBefore`
A trusted user can be granted multiple roles by the admin user to perform different operations.
The following functions can be called on the token contract by the admin user to grant and revoke roles to and from users.

## Provider & signer
#### Grant a role to a user

The following code example shows different ways to get the provider or signer:
```ts
const issuerRole = await documentStore.issuerRole();
await documentStore.grantRole(issuerRole, "0xIssuerStaff");
```

Can only be called by default admin or role admin.

#### Revoke a role from a user

```ts
import { Wallet, providers, getDefaultProvider } from "ethers";
const revokerRole = await documentStore.revokerRole();
await documentStore.revokeRole(revokerRole, "0xRevokerStaff");
```

Can only be called by default admin or role admin.

## Deployment

In all the deployment commands, you can replace `network` argument to any of the [supported networks](#supported-networks). Optionally, you can also supply `--verify=1` if you wish to verify the contracts.

> [!IMPORTANT]
> The `DEPLOYER_ADDRESS` in `.env` is required to be the address of the deployer. See [Configuration](#configuration) section.
### Document Store

#### Deploy a Document Store

```sh
npm run -s deploy:ds --network="mainnet" --name="My Document Store" --admin="0x1234"
```

The `name` is the name you want to have for the document store and the `admin` is the address who will be the default admin of the document store.

#### Deploy an upgradeable Document Store

```sh
npm run -s deploy:ds:upgradeable --network="mainnet" --name="My Document Store" --admin="0x1234" --verify=1
```

Note that in the example above, the `--verify=1` is optionally passed to verify the contracts.

// Providers
const mainnetProvider = getDefaultProvider();
const sepoliaProvider = getDefaultProvider("sepolia");
const metamaskProvider = new providers.Web3Provider(web3.currentProvider); // Will change network automatically
### Transferable Document Store

// Signer
const signerFromPrivateKey = new Wallet("YOUR-PRIVATE-KEY-HERE", provider);
const signerFromEncryptedJson = Wallet.fromEncryptedJson(json, password);
signerFromEncryptedJson.connect(provider);
const signerFromMnemonic = Wallet.fromMnemonic("MNEMONIC-HERE");
signerFromMnemonic.connect(provider);
#### Deploy a Transferable Document Store

```sh
npm run -s deploy:tds --network="mainnet" --name="My Transferable Document Store" --symbol="XYZ" --admin="0x1234" --verify=1
```

## Setup
The `name` and `symbol` are the standard ERC-721 token name and symbol respectively. The `admin` is the address who will be the default admin of the document store.

You can install dependencies, check source code, test your project, and use the Truffle development framework with the commands below:
#### Deploy an upgradeable Transferable Document Store

```sh
npm install
npm lint
npm test
npm truffle <command>
npm run -s deploy:tds:upgradeable --network="mainnet" --name="My Transferable Document Store" --symbol="XYZ" --admin="0x1234" --verify=1
```

## Contract benchmark
### Hardware Wallet

To deploy using a hardware wallet, you can set the `OA_LEDGER` environment variable to the HD path of your wallet. For example, `OA_LEDGER=m/44'/60'/0'/0/0`.

### Verification

You can pass `--verify=1` to the deployment commands if you wish to verify the contracts. You will need to include your Etherscan API keys for the respective networks in your `.env` configuration. See [Configuration](#configuration) section for more info.

### Supported Networks

Most EVM-based blockchains should support the document store contracts. For the more common blockchains listed below, we may deploy implementations to help reduce deployment gas fees.

- Ethereum
- Polygon
- Arbitrum One
- Optimism

> [!NOTE]
> For a list of pre-configured network names for passing to `--network` during deployment, refer to the [foundry.toml](foundry.toml#L28) file.
If you wish to deploy to a network not configured yet, you can add it to the `foundry.toml` file and pass the name of the network you've added to `--network` during deployment.

## Configuration

Create a `.env` file based on [`.env.example`](.env.sample) and provide the information in it.

The `DEPLOYER_ADDRESS` is required to be the address of the deployer during deployment. The Etherscan API keys are only required if you plan to verify the contracts on their respective chains.

# Development

To show the different transaction costs of the different variants of the document store, run the contract benchmark with the command below:
This repository uses [Foundry](https://github.com/foundry-rs/foundry) for its development. To install Foundry, run the following commands:

```sh
npm run benchmark
curl -L https://foundry.paradigm.xyz | bash
```

## Additional information
## Additional Information

If you are using Visual Studio Code, you may need to link the OpenZeppelin libraries. Refer to [here](https://github.com/juanfranblanco/vscode-solidity#openzeppelin) for more information.
Install lcov for test coverage report.
The contracts have not gone through formal audits yet. Please use them at your own discretion.
Binary file added docs/images/document-store-banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 6dc0eac

Please sign in to comment.