Skip to content

Commit

Permalink
demo/asset: Updates to have a VC of Asset (#196)
Browse files Browse the repository at this point in the history
  • Loading branch information
vatsa287 authored Apr 8, 2024
1 parent 235a575 commit 321a684
Show file tree
Hide file tree
Showing 2 changed files with 192 additions and 44 deletions.
31 changes: 31 additions & 0 deletions demo/res/asset_vc_schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$metadata": {
"version": "1.0.0",
"slug": "asset-demo-schema",
"discoverable": true
},
"title": "Asset Demo Schema v3",
"description": "Asset Demo Schema",
"properties": {
"assetType": {
"type": "string"
},
"assetDesc": {
"type": "string"
},
"assetQty": {
"type": "integer"
},
"assetValue": {
"type": "integer"
},
"assetTag": {
"type": "string"
},
"assetMeta": {
"type": "string"
}
},
"type": "object"
}
205 changes: 161 additions & 44 deletions demo/src/asset-vc-tx.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,59 @@
import * as Cord from "@cord.network/sdk";
import { addNetworkMember } from "./utils/createAuthorities.js";
import { createAccount } from "./utils/createAccount.js";
/*
import {
buildFromAssetProperties,
failproofSubmit,
buildFromAssetIssueProperties,
buildFromAssetTransferProperties,
} from "./utils/assets.js";
import { AssetTypeOf, IAssetProperties } from "./utils/asset-types.js";
*/

import * as vcExport from "@cord.network/vc-export";
import { createDid } from "./utils/generateDid";
import PalletAssetVcAssetEntry from '@polkadot/types/lookup';

const { NETWORK_ADDRESS, ANCHOR_URI } = process.env;

import { hashToUri, uriToIdentifier } from '@cord.network/identifier'
import {
ASSET_IDENT,
ASSET_PREFIX,
AssetUri,
IAssetEntry,
DidUri,
SpaceUri,
blake2AsHex,
AccountId,
H256,
} from '@cord.network/types'
import * as Did from '@cord.network/did'
import { HexString } from "@cord.network/types";

async function buildFromAssetVcProperties(entryDigest: HexString, issuerUri: DidUri , spaceUri: SpaceUri, api: Cord.ConfigService) {
const scaleEncodedAssetDigest = api
.createType<H256>("H256", entryDigest)
.toU8a();
const scaleEncodedIssuer = api
.createType<AccountId>('AccountId', Did.toChain(issuerUri))
.toU8a()
const scaleEncodedSpace = api
.createType<AccountId>('Bytes', uriToIdentifier(spaceUri))
.toU8a()

const assetIdDigest = blake2AsHex(
Uint8Array.from([...scaleEncodedAssetDigest, ...scaleEncodedSpace, ...scaleEncodedIssuer])
);

const assetIdentifier = hashToUri(
assetIdDigest,
ASSET_IDENT,
ASSET_PREFIX
) as AssetUri;

const transformedEntry: IAssetEntry = {
creator: issuerUri,
space: spaceUri,
digest: entryDigest,
uri: assetIdentifier,
};

return transformedEntry;
}

async function main() {
const networkAddress = NETWORK_ADDRESS ?? 'ws://127.0.0.1:9944';
const anchorUri = ANCHOR_URI ?? '//Alice';
Expand All @@ -41,7 +80,7 @@ async function main() {
await addNetworkMember(networkAuthorityIdentity, authorIdentity.address)

// const { account: issuerIdentity } = createAccount();
// Create issuer DID
// Create issuer DID
const { mnemonic: issuerMnemonic, document: issuerDid } = await createDid(
networkAuthorityIdentity
)
Expand Down Expand Up @@ -71,7 +110,7 @@ async function main() {
await addNetworkMember(networkAuthorityIdentity, apiIdentity.address);
console.log("✅ Identities created!");

// Step 3: Create a new Chain Space
// Step 2: Create a new Chain Space
console.log(`\n❄️ Chain Space Creation `)
const spaceProperties = await Cord.ChainSpace.buildFromProperties(
issuerDid.uri
Expand All @@ -81,15 +120,17 @@ async function main() {
colors: true,
})

let extSignCallback = async ({ data }) => ({
signature: issuerKeys.authentication.sign(data),
keyType: issuerKeys.authentication.type,
})

console.log(`\n❄️ Chain Space Properties `)
const space = await Cord.ChainSpace.dispatchToChain(
spaceProperties,
issuerDid.uri,
authorIdentity,
async ({ data }) => ({
signature: issuerKeys.authentication.sign(data),
keyType: issuerKeys.authentication.type,
})
extSignCallback,
)
console.dir(space, {
depth: null,
Expand All @@ -103,9 +144,34 @@ async function main() {
space.uri,
100
)
console.log(`✅ Chain Space Approved`)
console.log(`✅ Chain Space Approved`)

// Step 3: Dispatch creation of asset schema to chain.
let newSchemaContent = require('../res/asset_vc_schema.json');
let newSchemaName =
newSchemaContent.title + ':' + Cord.Utils.UUID.generate();
newSchemaContent.title = newSchemaName;

let schemaProperties = Cord.Schema.buildFromProperties(
newSchemaContent,
space.uri,
issuerDid.uri,
);

// Step 2: Create assets on-chain
const schemaUri = await Cord.Schema.dispatchToChain(
schemaProperties.schema,
issuerDid.uri,
authorIdentity,
space.authorization,
async ({ data }) => ({
signature: issuerKeys.authentication.sign(data),
keyType: issuerKeys.authentication.type,
}),
);

console.log(`✅ Schema - ${schemaUri} - added!`);

// Step 4: Create assets off-chain
let assetProperties: Cord.IAssetProperties = {
assetType: Cord.AssetTypeOf.art,
assetDesc: "Asset - " + Cord.Utils.UUID.generate(),
Expand All @@ -121,37 +187,71 @@ async function main() {
colors: true,
});

const assetEntry = await Cord.Asset.buildFromAssetProperties(
assetProperties,
issuerDid.uri,
space.uri,
);
// Step 5: Delegate(Asset Owner/Issuer) creates a new Verifiable Document
console.log(`\n❄️ VC Asset Creation `);

console.log(`\n❄️ Asset Transaction - Created by Issuer `);
console.dir(assetEntry, {
depth: null,
colors: true,
});
let newCredContent = await vcExport.buildVcFromContent(
schemaProperties.schema,
assetProperties,
issuerDid,
issuerDid.uri,
{
spaceUri: space.uri,
schemaUri: schemaUri,
},
);
/* TODO: Fix addProof dependency issue by implementing the methods requiring api locally */
// let vc = await vcExport.addProof(
// newCredContent,
// async (data) => ({
// signature: await issuerKeys.assertionMethod.sign(data),
// keyType: issuerKeys.assertionMethod.type,
// keyUri: `${issuerDid.uri}${
// issuerDid.assertionMethod![0].id
// }` as Cord.DidResourceUri,
// }),
// issuerDid,
// { spaceUri: space.uri, schemaUri, needSDR: false, needStatementProof: false },
// );
// console.dir(vc, {
// depth: null,
// colors: true,
// });

const assetVcEntry = await buildFromAssetVcProperties(newCredContent.credentialHash, issuerDid.uri, space.uri, api);
newCredContent.id = assetVcEntry.uri;
console.log("\n❄️ Asset(create) Verifiable Credential Document created \n", newCredContent);

const extrinsic = await Cord.Asset.dispatchCreateVcToChain(
assetProperties.assetQty,
assetEntry.digest,
assetEntry.creator,
newCredContent.credentialHash,
newCredContent.issuer,
networkAuthorityIdentity,
space.authorization,
assetEntry.uri,
async ({ data }) => ({
signature: issuerKeys.authentication.sign(data),
keyType: issuerKeys.authentication.type,
}),
assetVcEntry.uri,
extSignCallback,
)
console.log("\n✅ VC Asset created on-chain!");

console.log("✅ Asset created!");
// Update the assetProperties with number of quantity of asset issued.
let issuanceQty = 1;
assetProperties.assetQty = issuanceQty;

let newIssueCredContent = await vcExport.buildVcFromContent(
schemaProperties.schema,
assetProperties,
issuerDid,
holderDid.uri,
{
spaceUri: space.uri,
schemaUri: schemaUri,
},
);

// Step 3: Issue Asset to Holder
// Step 6: Issue Asset to Holder
console.log(`\n❄️ Issue Asset to Holder - Issuer Action `);
const assetIssuance = await Cord.Asset.buildFromIssueProperties(
assetEntry.uri,
assetVcEntry.uri,
holderDid.uri,
1,
issuerDid.uri,
Expand All @@ -163,18 +263,35 @@ async function main() {
colors: true,
});

// Asset Issue ID consists of both asset_id:instance_id
newIssueCredContent.id = assetIssuance.uri;
console.log("\n❄️ Asset(issue) Verifiable Credential Document created \n", newIssueCredContent);

const issueExtrinsic = await Cord.Asset.dispatchIssueVcToChain(
assetIssuance,
networkAuthorityIdentity,
space.authorization,
async ({ data }) => ({
signature: issuerKeys.authentication.sign(data),
keyType: issuerKeys.authentication.type,
}),
extSignCallback,
)

// Step 4: Transfer Asset to New Owner
// Step 7: Transfer Asset to New Owner
console.log(`\n❄️ Transfer Asset to New Owner (Holder2) - Holder Action `);

assetProperties.assetQty = issuanceQty;
let newTransferCredContent = await vcExport.buildVcFromContent(
schemaProperties.schema,
assetProperties,
holderDid,
holder2Did.uri,
{
spaceUri: space.uri,
schemaUri: schemaUri,
},
);

// Asset Issue ID consists of both asset_id:instance_id
newTransferCredContent.id = assetIssuance.uri;
console.log("\n❄️ Asset(transfer) Verifiable Credential Document created \n", newTransferCredContent);

const assetTransfer = await Cord.Asset.buildFromTransferProperties(
assetIssuance.uri,
Expand All @@ -196,7 +313,7 @@ async function main() {
}),
)

console.log("✅ Asset transferred!");
console.log("✅ Asset transferred!");
}
main()
.then(() => console.log("\nBye! 👋 👋 👋 "))
Expand Down

0 comments on commit 321a684

Please sign in to comment.