Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Registry-Entries: Add SDK module with Entry creation capability #246

Merged
merged 2 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions demo/src/registry-entries-tx.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import * as Cord from '@cord.network/sdk'
import { createAccount } from './utils/createAccount'

import {
BN
} from 'bn.js';

async function getBalance(address: string, api) {
Cord.ConfigService.set({ submitTxResolveOn: Cord.Chain.IS_IN_BLOCK })

const { data: balance } = await api.query.system.account(address);
return balance.free.toString(); // Returns free balance as a string
}

async function main() {
const networkAddress = process.env.NETWORK_ADDRESS
? process.env.NETWORK_ADDRESS
: 'ws://127.0.0.1:9944'

Cord.ConfigService.set({ submitTxResolveOn: Cord.Chain.IS_IN_BLOCK })
await Cord.connect(networkAddress)

const api = Cord.ConfigService.get('api');

// Step 1: Setup Membership
// Setup transaction author account - CORD Account.

console.log(`\n❄️ New Network Member`)
const authorityAuthorIdentity = Cord.Utils.Crypto.makeKeypairFromUri(
process.env.ANCHOR_URI ? process.env.ANCHOR_URI : '//Alice',
'sr25519'
)

// Setup network member account.
const { account: authorIdentity } = await createAccount()
console.log(`🏦 Member (${authorIdentity.type}): ${authorIdentity.address}`)

let tx = await api.tx.balances.transferAllowDeath(authorIdentity.address, new BN('1000000000000000'));
await Cord.Chain.signAndSubmitTx(tx, authorityAuthorIdentity);

// Create a Registry.
const blob = {
"name": "Companies Registry",
"description": "A centralized registry that tracks the registration, incorporation status, and key business details of companies across various industries.",
"metadata": {
"category": "business",
"totalCompaniesRegistered": 15000,
"industriesCovered": [
"Technology",
"Healthcare",
"Renewable Energy",
"Finance",
"Manufacturing"
],
"lastUpdated": "01-10-2024",
"regulatoryAuthority": "National Business Bureau",
"registrationRequirements": {
"documentsNeeded": [
"Incorporation Certificate",
"Tax Identification Number",
"Proof of Address",
"Board Resolution"
],
"feeStructure": {
"smallBusiness": "INR500",
"mediumBusiness": "INR1000",
"largeBusiness": "INR5000"
}
}
}
};
const stringified_blob = JSON.stringify(blob);
const digest = await Cord.Registries.getDigestFromRawData(stringified_blob);

// Crreate a Registry Property.
const registryDetails = await Cord.Registries.registryCreateProperties(
authorIdentity.address,
digest, //digest
null, //schemaId
blob, //blob
);

console.log(`\n❄️ Registry Create Details `, registryDetails);

// Dispatch the Registry Property to the chain.
const registry = await Cord.Registries.dispatchCreateRegistryToChain(
registryDetails,
authorIdentity,
);

console.log('\n✅ Registry created!');

// Create a Registry Entry.
const entryBlob = {
"name": "Tech Solutions Ltd.",
"description": "A technology company providing software development and IT consulting services.",
"metadata": {
"category": "Technology",
"registrationDate": "15-06-2022",
"status": "Active",
"registrationNumber": "TSL12345",
"industry": "Technology",
"regulatoryAuthority": "National Business Bureau",
"documentsProvided": [
"Incorporation Certificate",
"Tax Identification Number",
"Proof of Address",
"Board Resolution"
],
"feePaid": "INR500",
"lastUpdated": "01-10-2024"
}
};
const stringifiedEntryBlob = JSON.stringify(entryBlob);
const entryDigest = await Cord.Registries.getDigestFromRawData(stringifiedEntryBlob);

// Create a Registry Entry Properties.
const registryEntryDetails = await Cord.Entries.CreateEntriesProperties(
authorIdentity.address,
entryDigest, //digest
entryBlob, //blob
registry.uri, //registryUri
registry.authorizationUri //registryAuthUri
);

console.log(`\n❄️ Registry Entry Create Details `, registryEntryDetails);

// Dispatch the Registry Entry to the chain.
const registryEntry = await Cord.Entries.dispatchCreateEntryToChain(
registryEntryDetails,
authorIdentity,
)

console.log('\n✅ Registry Entry created!');
}

main()
.then(() => console.log('\nBye! 👋 👋 👋 '))
.finally(Cord.disconnect)

process.on('SIGINT', async () => {
console.log('\nBye! 👋 👋 👋 \n')
Cord.disconnect()
process.exit(0)
})
43 changes: 43 additions & 0 deletions packages/entries/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "@cord.network/entries",
"version": "0.9.3-1rc4",
"description": "CORD Registry Entry Management",
"main": "./lib/cjs/index.js",
"module": "./lib/esm/index.js",
"types": "./lib/cjs/index.d.ts",
"exports": {
".": {
"import": "./lib/esm/index.js",
"require": "./lib/cjs/index.js"
}
},
"files": [
"lib/**/*"
],
"scripts": {
"clean": "rimraf ./lib",
"build": "yarn clean && yarn build:ts",
"build:ts": "yarn build:cjs && yarn build:esm",
"build:cjs": "tsc --declaration -p tsconfig.build.json && echo '{\"type\":\"commonjs\"}' > ./lib/cjs/package.json",
"build:esm": "tsc --declaration -p tsconfig.esm.json && echo '{\"type\":\"module\"}' > ./lib/esm/package.json"
},
"repository": "github:dhiway/cord-js",
"engines": {
"node": ">=20.0"
},
"author": "Dhiway",
"bugs": "https://github.com/dhiway/cord.js/issues",
"homepage": "https://github.com/dhiway/cord.js#readme",
"devDependencies": {
"rimraf": "^5.0.5",
"typescript": "^5.3.3"
},
"dependencies": {
"@cord.network/config": "workspace:*",
"@cord.network/identifier": "workspace:*",
"@cord.network/network": "workspace:*",
"@cord.network/registries": "workspace:*",
"@cord.network/types": "workspace:*",
"@cord.network/utils": "workspace:*"
}
}
118 changes: 118 additions & 0 deletions packages/entries/src/Entries.chain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/**
* @packageDocumentation
* @module Entries/chain
*
* The Entries module, a crucial part of the `DeDir (Decentralized Directory)`, provides a framework for
* managing decentralized entries or records within registries on the CORD blockchain. It enables
* the creation, updating, revocation, and reinstatement of entries in a transparent and trustless manner,
* ensuring that registries are managed in a decentralized environment. The Registries module manages
* governance and delegation for these registries.
*
* ## Overview
*
* The Entries module allows for the creation and modification of individual registry entries, each
* representing a unique record within a registry. These entries can be updated, revoked, or reinstated
* through a permissioned system. The decentralized nature of this module ensures trust, transparency,
* and immutability for registry entries on the CORD blockchain.
*
* ## Interface
*
* The Entries module provides several functions for managing registry entries:
*
* - `dispatchCreateToChain`: Creates a new registry entry in a decentralized registry.
* - `dispatchUpdateToChain`: Updates an existing registry entry with new data.
* - `dispatchRevokeToChain`: Revokes a registry entry, marking it as inactive or invalid.
* - `dispatchReinstateToChain`: Restores a revoked registry entry to an active state.
*
* ## Usage
*
* The Entries module integrates with the Registries module to offer a decentralized directory
* management system. It can be used in various applications requiring transparent and decentralized
* record management, such as credential registries, asset tracking, or any system needing immutable
* and auditable records.
*
* ## Examples
*
* - Create an entry for a verifiable credential in a decentralized identity registry.
* - Revoke an entry that is no longer valid or relevant.
* - Reinstate an entry after resolving governance issues or discrepancies.
*
*/
import {
CordKeyringPair,
} from '@cord.network/types';

import { SDKErrors } from '@cord.network/utils';

import {
IRegistryEntry, EntryUri
} from '@cord.network/types';

import { Chain } from '@cord.network/network';

import { ConfigService } from '@cord.network/config'

import {
uriToIdentifier,
} from '@cord.network/identifier'

/**
* Dispatches the creation of a new registry entry to the CORD blockchain by submitting an extrinsic.
*
* This method constructs and submits an `entries.create` extrinsic to the CORD blockchain, allowing
* for the creation of a new registry entry. It takes the details of the entry, such as the registry entry URI,
* authorization URI, digest, and blob, and signs the transaction using the provided author account.
*
* @param {IRegistryEntry} registryEntryDetails - The details of the registry entry to be created, including the URI, authorization URI, digest, and blob.
* @param {CordKeyringPair} authorAccount - The account (keyring pair) that will be used to sign and submit the extrinsic to the blockchain.
*
* @returns {Promise<EntryUri>} - A promise that resolves to the URI of the created registry entry if the transaction is successful.
*
* @throws {SDKErrors.CordDispatchError} - Throws an error if the transaction fails or encounters an issue during submission.
*
* @example
* ```typescript
* const registryEntryDetails = {
* uri: 'entryUri123',
* authorizationUri: 'authUri456',
* digest: '0x123...',
* blob: '{"key": "value"}'
* };
*
* const authorAccount = await CordKeyring.createFromUri('//Alice');
*
* try {
* const entryUri = await dispatchCreateEntryToChain(registryEntryDetails, authorAccount);
* console.log('Registry Entry created with URI:', entryUri);
* } catch (error) {
* console.error('Error creating registry entry:', error);
* }
* ```
*/
export async function dispatchCreateEntryToChain(
registryEntryDetails: IRegistryEntry,
authorAccount: CordKeyringPair
): Promise<EntryUri> {
try {
const api = ConfigService.get('api');

const registryEntryId = uriToIdentifier(registryEntryDetails.uri);
const authorizationId = uriToIdentifier(registryEntryDetails.authorizationUri);

const extrinsic = api.tx.entries.create(
registryEntryId,
authorizationId,
registryEntryDetails.digest,
registryEntryDetails.blob,
);

await Chain.signAndSubmitTx(extrinsic, authorAccount);
return registryEntryDetails.uri;
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : JSON.stringify(error);
throw new SDKErrors.CordDispatchError(
`Error dispatching to chain: "${errorMessage}".`
);
}
}
Loading