Skip to content

Commit

Permalink
feat: Integrate v2protos (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
DaevMithran authored Jan 3, 2023
2 parents 86a46e1 + df88ac9 commit 4b416a1
Show file tree
Hide file tree
Showing 8 changed files with 509 additions and 244 deletions.
367 changes: 189 additions & 178 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
"build": "esbuild src/index.ts --platform=node --bundle --minify --outdir=dist --external:swagger-ui-express"
},
"dependencies": {
"@cheqd/sdk": "1.4.0-develop.1",
"@cheqd/ts-proto": "^1.0.13",
"@cheqd/sdk": "^1.5.0-develop.1",
"@cheqd/ts-proto": "^1.0.16-develop.2",
"@cosmjs/proto-signing": "^0.29.2",
"dotenv": "^16.0.3",
"express": "^4.18.2",
Expand All @@ -41,6 +41,7 @@
"@types/node": "^18.11.4",
"@types/node-fetch": "^2.6.2",
"@types/swagger-ui-express": "^4.1.3",
"@types/uuid": "^9.0.0",
"@typescript-eslint/eslint-plugin": "^5.40.1",
"@typescript-eslint/parser": "^5.40.1",
"conventional-changelog-conventionalcommits": "^5.0.0",
Expand Down
6 changes: 4 additions & 2 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { CheqdRegistrar } from './service/cheqd'
import * as swagger from 'swagger-ui-express'
import * as swaggerJson from '../swagger.json'
import { CheqdController } from './controllers/cheqd'
import { ResourceController } from './controllers/resource'

class App {
public express: express.Application
Expand All @@ -31,8 +32,9 @@ class App {

// did-registrar
app.post(`${URL_PREFIX}/create`, DidController.createValidator, new DidController().create)
app.post(`${URL_PREFIX}/update`, DidController.updateValidator, new DidController().update)
app.post(`${URL_PREFIX}/deactivate`, (req,res)=>res.send('To be implemented'))
app.post(`${URL_PREFIX}/update`, DidController.createValidator, DidController.updateValidator, new DidController().update)
app.post(`${URL_PREFIX}/deactivate`, DidController.createValidator, new DidController().deactivate)
app.post(`${URL_PREFIX}/:did/create-resource`, new ResourceController().create)

// cheqd-helpers
app.get(`${URL_PREFIX}/key-pair`, new CheqdController().generateKeys)
Expand Down
106 changes: 81 additions & 25 deletions src/controllers/did.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IKeyPair, ISignInputs } from '@cheqd/sdk/build/types'
import { createDidPayloadWithSignInputs, createSignInputsFromKeyPair } from '@cheqd/sdk/build/utils'
import { MsgCreateDidPayload } from '@cheqd/ts-proto/cheqd/v1/tx'
import { Request, Response } from 'express'
import { MsgCreateDidDocPayload } from '@cheqd/ts-proto/cheqd/did/v2'
import e, { Request, Response } from 'express'
import { validationResult, check } from 'express-validator'
import { jsonConcat, jsonSubtract, randomStr } from '../helpers/helpers'
import { CheqdRegistrar, CheqdResolver } from '../service/cheqd'
Expand All @@ -14,9 +14,12 @@ export class DidController {
if (value) {
if(value.seed && value.keys) return false
else if(value.seed && value.seed.length != 32 ) return false
else {
return value.keys.every((key: any) => key.privateKey.length == 86 && key.publicKey.length == 43
)}
}
return true
}).withMessage('Only one of seed or keys should be provided, Seed length should be 32')
}).withMessage('Only one of seed or keys should be provided, Seed length should be 32, Keypair should be valid')
]

public static updateValidator = [
Expand All @@ -39,9 +42,9 @@ export class DidController {

secret = secret || { seed: randomStr() }

await CheqdRegistrar.instance.connect(options?.network)
await CheqdRegistrar.instance.connect(options?.network, secret.mnemonic)

let didPayload: Partial<MsgCreateDidPayload>, signInputs: ISignInputs[], keys: IKeyPair[]
let didPayload: Partial<MsgCreateDidDocPayload>, signInputs: ISignInputs[], keys: IKeyPair[]
if (didDocument && secret.keys) {
didPayload = didDocument
signInputs = createSignInputsFromKeyPair(didDocument, secret.keys)
Expand All @@ -54,16 +57,22 @@ export class DidController {
}

try {
await CheqdRegistrar.instance.create(signInputs, didPayload)
return response.status(201).json({
jobId: null,
didState: {
did: didPayload.id,
state: "finished",
secret: { keys },
didDocument: didPayload
}
})
const result = await CheqdRegistrar.instance.create(signInputs, didPayload)
if ( result.code == 0 ) {
return response.status(201).json({
jobId: null,
didState: {
did: didPayload.id,
state: "finished",
secret: { keys },
didDocument: didPayload
}
})
} else {
return response.status(404).json({
message: `Invalid payload: ${JSON.stringify(result.rawLog)}`
})
}
} catch (error) {
return response.status(500).json({
message: `Internal server error: ${error}`
Expand All @@ -90,7 +99,7 @@ export class DidController {
message: `${did} DID not found`
})
}
console.log(didDocumentOperation)

var i=0
let updatedDocument = resolvedDocument.didDocument
for (var operation of didDocumentOperation) {
Expand All @@ -112,20 +121,67 @@ export class DidController {

try {
const signInputs = createSignInputsFromKeyPair(updatedDocument, secret.keys)
await CheqdRegistrar.instance.update(signInputs, updatedDocument)
return response.status(201).json({
jobId: null,
didState: {
did: updatedDocument.id,
state: "finished",
secret,
didDocument: updatedDocument
}
const result = await CheqdRegistrar.instance.update(signInputs, updatedDocument)
if ( result.code == 0 ) {
return response.status(201).json({
jobId: null,
didState: {
did: updatedDocument.id,
state: "finished",
secret,
didDocument: updatedDocument
}
})
} else {
return response.status(404).json({
message: `Invalid payload: ${JSON.stringify(result.rawLog)}`
})
}
} catch (error) {
return response.status(500).json({
message: `Internal server error: ${error}`
})
}
}

public async deactivate (request: Request, response: Response) {
const { secret, options, did } = request.body as IDIDUpdateRequest
await CheqdRegistrar.instance.connect(options?.network)
// check if did is registered on the ledger
let resolvedDocument = await CheqdResolver(did)
if(!resolvedDocument?.didDocument) {
return response.status(400).send({
message: `${did} DID not found`
})
}

try {
const signInputs = createSignInputsFromKeyPair(resolvedDocument, secret.keys)
const result = await CheqdRegistrar.instance.deactivate(signInputs, {
verificationMethod: resolvedDocument.verificationMethod,
versionId: resolvedDocument.didDocumentMetadata.versionId,
id: did
})
if ( result.code == 0 ) {
return response.status(201).json({
jobId: null,
didState: {
did: did,
state: "finished",
secret
}
})
} else {
return response.status(404).json({
message: `Invalid payload: ${JSON.stringify(result.rawLog)}`
})
}
} catch (error) {
return response.status(500).json({
message: `Internal server error: ${error}`
})
}


}
}
57 changes: 57 additions & 0 deletions src/controllers/resource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { AlternativeUri, MsgCreateResourcePayload } from '@cheqd/ts-proto/cheqd/resource/v2'
import { Request, Response } from 'express'
import { CheqdRegistrar, NetworkType } from '../service/cheqd'
import { v4 as uuid } from 'uuid'
import { check, param, query, validationResult } from 'express-validator'
import { IKeyPair, ISignInputs } from '@cheqd/sdk/build/types'
import { toString, fromString } from 'uint8arrays'
import { IResourceCreateRequest } from '../types/types'

export class ResourceController {

public static createValidator = [
check('name').exists().isString().withMessage('Resource name is required'),
check('type').exists().isString().withMessage('Resource type is required'),
check('secret').exists().isObject().withMessage('Secret is required'),
param('did').exists().isString().contains('did:cheqd').withMessage('DID is required'),
]

public async create(request: Request, response: Response) {
console.log(request.query)
const result = validationResult(request);
if (!result.isEmpty()) {
return response.status(400).json({
message: result.array()[0].msg
})
}
const { did } = request.params
console.log(did, "DID")
let { data, name, type, mimeType, alsoKnownAs, version, secret } = request.body as IResourceCreateRequest
if(mimeType == 'json') {
data = JSON.stringify(data)
}

const resourcePayload: MsgCreateResourcePayload = {
collectionId: did.split(':').pop()!,
id: uuid(),
name,
resourceType: type,
data: Buffer.from(data),
version,
alsoKnownAs: alsoKnownAs || []
}
let signInputs: ISignInputs[] = []
secret.keys.map((key: IKeyPair, i: any)=>{
signInputs.push({
verificationMethodId: did+`#key-1`,
keyType: 'Ed25519',
privateKeyHex: toString(fromString(key.privateKey, 'base64'), 'hex')
})
})
await CheqdRegistrar.instance.connect(NetworkType.Testnet)
const resp = await CheqdRegistrar.instance.createResource(signInputs, resourcePayload)
return response.json({
status: resp
})
}
}
76 changes: 52 additions & 24 deletions src/service/cheqd.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import type { ICheqdSDKOptions } from '@cheqd/sdk'
import { ICheqdSDKOptions, ResourceModule } from '@cheqd/sdk'
import type { AbstractCheqdSDKModule } from '@cheqd/sdk/build/modules/_'
import type { ISignInputs } from '@cheqd/sdk/build/types'
import type { MsgCreateDidPayload, MsgUpdateDidPayload } from '@cheqd/ts-proto/cheqd/v1/tx'
import type { DidStdFee, ISignInputs, MsgDeactivateDidPayload } from '@cheqd/sdk/build/types'
import type { MsgCreateDidDocPayload, MsgUpdateDidDocPayload } from '@cheqd/ts-proto/cheqd/did/v2'

import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing'
import { DirectSecp256k1HdWallet, OfflineSigner } from '@cosmjs/proto-signing'
import { CheqdSDK, createCheqdSDK, DIDModule } from '@cheqd/sdk'
import * as dotenv from 'dotenv'
import fetch from 'node-fetch'
import { MsgCreateResourcePayload } from '@cheqd/ts-proto/cheqd/resource/v2'

dotenv.config()

const { FEE_PAYER_MNEMONIC, FEE_PAYER_ADDRESS } = process.env

const FEE = { amount: [{ denom: 'ncheq', amount: '5000000' }], gas: '200000', payer: FEE_PAYER_ADDRESS }
const { FEE_PAYER_MNEMONIC } = process.env

export enum DefaultRPCUrl {
Mainnet = 'https://rpc.cheqd.net',
Testnet = 'https://rpc.cheqd.network'
Testnet = 'http://localhost:26657'
}

export enum NetworkType {
Expand All @@ -30,23 +29,29 @@ export enum DefaultResolverUrl {

export class CheqdRegistrar {
private sdk?: CheqdSDK
private address?: string
private fee?: DidStdFee

public static instance = new CheqdRegistrar()

constructor() {
if(!FEE_PAYER_MNEMONIC && !FEE_PAYER_ADDRESS) {
throw new Error('No faucet address provided')
public async connect(network?: NetworkType, mnemonic?: string, wallet?: OfflineSigner) {
if(!(wallet || mnemonic || FEE_PAYER_MNEMONIC)) {
throw new Error('No signer provided')
}
}

public async connect(network?: NetworkType) {
if (this.sdk) return

const sdkOptions: ICheqdSDKOptions = {
modules: [DIDModule as unknown as AbstractCheqdSDKModule],
modules: [DIDModule as unknown as AbstractCheqdSDKModule, ResourceModule as unknown as AbstractCheqdSDKModule],
rpcUrl: network === NetworkType.Mainnet ? DefaultRPCUrl.Mainnet : DefaultRPCUrl.Testnet,
wallet: await DirectSecp256k1HdWallet.fromMnemonic(FEE_PAYER_MNEMONIC!, {prefix: 'cheqd'})
wallet: wallet || await DirectSecp256k1HdWallet.fromMnemonic(mnemonic || FEE_PAYER_MNEMONIC, {prefix: 'cheqd'})
}
this.sdk = await createCheqdSDK(sdkOptions)

this.address = (await sdkOptions.wallet.getAccounts())[0].address
if(!this.address) {
throw new Error("Invalid signer")
}

this.fee = { amount: [{ denom: 'ncheq', amount: '5000000000' }], gas: '200000', payer: this.address }
}

public forceGetSdk(): CheqdSDK{
Expand All @@ -56,25 +61,48 @@ export class CheqdRegistrar {
return this.sdk
}

public async create(signInputs: ISignInputs[], didPayload: Partial<MsgCreateDidPayload>) {
public async create(signInputs: ISignInputs[], didPayload: Partial<MsgCreateDidDocPayload>) {
return await this.forceGetSdk()
.createDidTx(
signInputs,
didPayload,
FEE_PAYER_ADDRESS,
FEE,
this.address!,
this.fee!,
undefined,
{ sdk: this.forceGetSdk() }
)
}

public async update(signInputs: ISignInputs[], didPayload: Partial<MsgUpdateDidPayload>) {
public async update(signInputs: ISignInputs[], didPayload: Partial<MsgUpdateDidDocPayload>) {
return await this.forceGetSdk()
.updateDidTx(
signInputs,
didPayload,
FEE_PAYER_ADDRESS,
FEE,
this.address!,
this.fee!,
undefined,
{ sdk: this.forceGetSdk() }
)
}

public async deactivate(signInputs: ISignInputs[], didPayload: MsgDeactivateDidPayload) {
return await this.forceGetSdk()
.deactivateDidTx(
signInputs,
didPayload,
this.address!,
this.fee!,
undefined,
{ sdk: this.forceGetSdk() }
)
}

public async createResource(signInputs: ISignInputs[], resourcePayload: Partial<MsgCreateResourcePayload>) {
return await this.forceGetSdk().createResourceTx(
signInputs,
resourcePayload,
this.address!,
this.fee!,
undefined,
{ sdk: this.forceGetSdk() }
)
Expand Down
Loading

0 comments on commit 4b416a1

Please sign in to comment.