@elysium-onchain-id/identity-sdk
Version:
Interact with BlockChain Identities.
336 lines (232 loc) • 10.1 kB
Markdown
# IDENTITY SDK
> This package facilitates the interaction with Identities stored in the BlockChain.
## Specifications
### Features
- Deploy identities
- List and Manage keys on an Identity
- List and manage Claims on an Identity.
- Issue claims for an Identity.
- Fetch claim data using their URI.
---
## Usage
### Installation
**Install with `npm install @onchain-id/identity-sdk`**
Then require with:
```javascript
const { IdentitySDK } = require('@onchain-id/identity-sdk');
```
### Tutorials
- [Tutorial Homepage](./docs/tutorials/README.md)
- [Implement a Claim Issuer service](./docs/tutorials/implement%20a%20claim%20issuer.md)
- [Restrict access to compliant Identities](./docs/tutorials/restrict%20to%20compliant%20identities.md)
- [Connect with Identity](./docs/tutorials/connect%20with%20identity.md)
### BlockChain Provider
To interact with the BlockChain, you will need to instantiate a Provider.
The SDK is using [Ethers](https://github.com/ethers-io/ethers.js) to connect with Ethereum network.
Thus, any provider supported by Ethers can be used with the SDK.
This means any standard web3 provider should by supported.
Connect to a default provider:
```javascript
// You can use any standard network name
// - "homestead"
// - "rinkeby"
// - "ropsten"
// - "kovan"
const ethers = require('ethers');
const provider = ethers.getDefaultProvider('ropsten');
const identity = await Identity.at('0x...', { provider });
```
Connect to JSON RPC:
```javascript
// When using the JSON-RPC API, the network will be automatically detected
// Default: http://localhost:8545
let httpProvider = new ethers.providers.JsonRpcProvider();
```
Connect to any Web3 Provider:
```javascript
// When using a Web3 provider, the network will be automatically detected
// e.g. HTTP provider
let currentProvider = new web3.providers.HttpProvider('http://localhost:8545');
let web3Provider = new ethers.providers.Web3Provider(currentProvider);
```
Connect to metamask:
```javascript
// The network will be automatically detected; if the network is
// changed in MetaMask, it causes a page refresh.
let provider = new ethers.providers.Web3Provider(web3.currentProvider);
```
To use a signer instead of a provider (required to sign transactions):
```javascript
const signer = new ethers.Wallet('PRIVATE_KEY', provider); // Or other signers from EthersJS.
const identity = await Identity.at('0x...', { signer });
```
> Please refer to the [Ethers Providers Documentation](https://docs.ethers.io/ethers.js/html/api-providers.html) for more information.
#### Overriding provider or signer for operation
Every methods that connects to the Blockchain (write or read) accept last `options` arguments to specify the
signer or provider to use for the operation, and for write operation, to override transaction parameters:
```javascript
const ethers = require('ethers');
const identity = new IdentitySDK.Identity('0xadD92F8Ef0729E969c5a98Ea5740c9b644B362e3', provider);
await identity.addKey('0x..', 1, 3, { signer: someSigner, overrides: { gasPrice: ethers.parseUnits('2.0', 'gwei') } });
```
### Configuration
#### Providers
By default, unsecured providers are not allowed. The SDK will refuse to fetch data on these endpoints.
A claim that has an uri which is not an HTTPS endpoint won't be retrieved.
Allow unsecured endpoints with:
```
const IdentitySDK = require('@onchain-id/identity-sdk');
IdentitySDK.Config.config({ allowUnsecuredProviders: true });
```
### SignerModule
Many interaction with identities, and especially claims, require to sign a challenge message.
Functions requiring these signatures expect a SignerModule as argument.
A SignerModule must expose a .getPublicKey() and a .signMessage(message: string) functions.
This is, for instance, a valid SignerModule:
```javascript
const jsrasign = require('jsrasign');
const signer = new SignerModule({
getPublicKey: async () => ({
key: "-----BEGIN CERTIFICATE----- my_super_public_key -----END CERTIFICATE-----",
type: "X.509",
signingMethod: "SHA-256",
}),
signMessage: async (message) => {
const signer = new jsrsasign.Signature({ alg: 'SHA256withRSA' });
signer.init("-----BEGIN CERTIFICATE----- my_super_PRIVATE_no_really_super_secret_PRIVATE_key -----END CERTIFICATE-----");
signer.updateString(message);
return signer.sign();
},
});
```
As a convenient method, a SignerModule can be created from an ethers Wallet:
```javascript
const wallet = new IdentitySDK.Providers.Wallet('PRIVATE_KEY', provider);
const signer = new IdentitySDK.SignerModule(wallet);
```
### Examples
Find examples in the [Example folder](./examples).
#### Load a contract
```javascript
const { IdentitySDK } = require('@onchain-id/identity-sdk');
const provider = new ethers.providers.JsonRpcProvider();
(async () => {
const identity = new IdentitySDK.Identity(); // Create the Identity Object
console.log(identity.instantiateAtAddress('0xadD92F8Ef0729E969c5a98Ea5740c9b644B362e3', provider)); // Get the instance of the Identity
console.log(await identity.instance.getClaimIdsByTopic(1)); // Call directly a function from the Contract.
})();
```
#### Get claims of an Identity
```javascript
const { IdentitySDK } = require('@onchain-id/identity-sdk');
const provider = new ethers.providers.JsonRpcProvider();
(async () => {
const identity = new IdentitySDK.Identity('0xadD92F8Ef0729E969c5a98Ea5740c9b644B362e3', provider);
const claims = await identity.getClaimsByTopic(1);
console.log(claims);
})();
```
#### Get keys of an Identity
```javascript
const { IdentitySDK } = require('@onchain-id/identity-sdk');
const provider = new ethers.providers.JsonRpcProvider();
(async () => {
const identity = new IdentitySDK.Identity('0xadD92F8Ef0729E969c5a98Ea5740c9b644B362e3', provider);
const keys = await identity.getKeysByPurpose(IdentitySDK.utils.enums.KeyPurpose.CLAIM);
console.log(keys);
console.log(await identity.getKeyPurposes(keys[0].key));
})();
```
#### Deploy an identity
```javascript
const { IdentitySDK } = require('@onchain-id/identity-sdk');
const provider = new ethers.providers.JsonRpcProvider();
const CLAIM_ISSUER_PRIVATE_KEY = 'issuer_private_key';
const claimIssuerWallet = new IdentitySDK.Providers.Wallet(CLAIM_ISSUER_PRIVATE_KEY, provider);
const DEPLOY_PRIVATE_KEY = 'deploy_private_key';
const deployWallet = new IdentitySDK.Providers.Wallet(DEPLOY_PRIVATE_KEY, provider);
(async () => {
// Deploy a new Identity
const identity = await IdentitySDK.Identity.deployNew(
{
managementKey: deployWallet.address,
implementationAuthority: IdentitySDK.constants.implementationAuthorities.kovan,
},
{ signer: deployWallet }
);
await identity.deployed();
await identity.addKey(IdentitySDK.utils.crypto.keccak256(claimIssuerWallet.address), IdentitySDK.utils.enums.KeyPurpose.CLAIM, IdentitySDK.utils.enums.KeyType.ECDSA);
identity.useProvider(claimIssuerWallet);
await identity.addClaim(IdentitySDK.utils.enums.ClaimTopic.KYC, IdentitySDK.utils.enums.ClaimScheme.SOME, claimIssuerWallet.address, "a signature", "what a lot of data", "http://localhost:8080/claims/666");
})();
```
#### Deploy an implementation
```javascript
const ethers = require('ethers');
const OnchainID = require('@onchain-id/solidity');
(async () => {
const provider = ethers.getDefaultProvider('kovan');
const signer = new ethers.Wallet('<private key>', provider);
const implementation = await new ethers.ContractFactory(
OnchainID.contracts.Identity.abi,
OnchainID.contracts.Identity.bytecode,
signer
).deploy(
signer.address,
true,
);
await implementation.deployed();
console.log(implementation.address);
})();
```
#### Deploy an implementation authority
```javascript
const ethers = require('ethers');
const OnchainID = require('@onchain-id/solidity');
(async () => {
const provider = ethers.getDefaultProvider('kovan');
const signer = new ethers.Wallet('<private key>', provider);
const implementationAddress = '<implementation address>';
const implementationAuthority = await new ethers.ContractFactory(
OnchainID.contracts.ImplementationAuthority.abi,
OnchainID.contracts.ImplementationAuthority.bytecode,
signer
).deploy(implementationAddress);
await implementationAuthority.deployed();
console.log(implementationAuthority.address);
})();
```
---
#### Get details of a claim
```javascript
const { IdentitySDK } = require('@onchain-id/identity-sdk');
const provider = new ethers.providers.JsonRpcProvider();
(async () => {
IdentitySDK.config({ allowUnsecuredProviders: true });
const identity = new IdentitySDK.Identity('0xadD92F8Ef0729E969c5a98Ea5740c9b644B362e3', provider);
const claims = await identity.getClaimsByTopic(IdentitySDK.utils.enums.ClaimTopic.KYC);
const claim = new IdentitySDK.Claim(claims[0]);
await claim.populate();
console.log(claim);
/*
Claim {
data: '0x65773261724950755a302f626e5a744e327961676676376139462f6a3672744a4e3761666a52414c6871493d',
id: '0x3c6532cc1f4d1a44de8f58d4bde617bef8e744168bf92d783a0e1b66e7c6a44a',
issuer: '0x8c78fF753c63ea0e8CA1FcA9997A132bC3e6a8F1',
scheme: 1,
topic: 1,
uri: 'http://localhost:8080/claims/b701e350-2a08-11e9-ac7e-517ddf10b60e',
issuanceDate: 2019-02-06T12:14:12.996Z,
emissionDate: 2019-02-06T12:15:02.039Z,
status: 'PENDING',
publicData: { result: 'clear' } }
*/
})();
```
## Development
- Install dependencies: `yarn`.
- Lint code with `yarn lint`.
- Run unit tests: `yarn test:unit`. You can run unit tests each time you modify a file with `yarn test:unit:watch`.
- Build project with `yarn build`. This will build package into the `dist/` folder from the TypeScript sources.
- Run end to end tests against a builded package: `yarn test:e2e`.
- You can generate type documentation with `yarn build:docs`. This will build the TypeDoc website into `docs/type_doc`.