Skip to content

Commit

Permalink
feat!: On track with v1 on-ledger release (#115)
Browse files Browse the repository at this point in the history
* feat!: On track with v1 on-ledger release

* Switched target to localnet
  • Loading branch information
Eengineer1 committed Jan 26, 2023
1 parent 658f31b commit 1ef3a07
Show file tree
Hide file tree
Showing 14 changed files with 972 additions and 537 deletions.
19 changes: 10 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
},
"homepage": "https://github.com/cheqd/sdk#readme",
"dependencies": {
"@cheqd/ts-proto": "^1.0.16-develop.3",
"@cheqd/ts-proto": "^2.0.0-develop.1",
"@cosmjs/amino": "^0.29.4",
"@cosmjs/encoding": "^0.29.4",
"@cosmjs/math": "^0.29.4",
Expand All @@ -37,6 +37,7 @@
"@stablelib/ed25519": "^1.0.3",
"cosmjs-types": "^0.5.2",
"did-jwt": "^6.9.0",
"did-resolver": "^4.0.1",
"multiformats": "^9.9.0",
"uuid": "^9.0.0"
},
Expand Down
7 changes: 5 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import { createDefaultCheqdRegistry } from './registry'
import { CheqdSigningStargateClient } from './signer'
import { CheqdNetwork, IContext, IModuleMethodMap } from './types'
import { createSignInputsFromImportableEd25519Key } from './utils'
import { GasPrice } from '@cosmjs/stargate'

export interface ICheqdSDKOptions {
modules: AbstractCheqdSDKModule[]
authorizedMethods?: string[]
network?: CheqdNetwork
rpcUrl: string
network?: CheqdNetwork
gasPrice?: GasPrice
authorizedMethods?: string[]
readonly wallet: OfflineSigner
}

Expand Down Expand Up @@ -78,6 +80,7 @@ export class CheqdSDK {
this.options.wallet,
{
registry,
gasPrice: this.options?.gasPrice,
}
)

Expand Down
205 changes: 189 additions & 16 deletions src/modules/did.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,41 @@ import { createProtobufRpcClient, DeliverTxResponse, QueryClient } from "@cosmjs
/* import { QueryClientImpl } from '@cheqd/ts-proto/cheqd/did/v1/query' */
import { CheqdExtension, AbstractCheqdSDKModule, MinimalImportableCheqdSDKModule } from "./_"
import { CheqdSigningStargateClient } from "../signer"
import { DidStdFee, IContext, ISignInputs, MsgCreateDidPayload, MsgDeactivateDidPayload, MsgUpdateDidPayload, VerificationMethodPayload } from "../types"
import { DIDDocument, DidStdFee, IContext, ISignInputs, SpecValidationResult, VerificationMethods } from '../types';
import {
MsgCreateDidDoc,
MsgCreateDidDocPayload,
MsgCreateDidDocResponse,
MsgDeactivateDidDoc,
MsgDeactivateDidDocPayload,
MsgDeactivateDidDocResponse,
MsgUpdateDidDoc,
MsgUpdateDidDocPayload,
MsgUpdateDidDocResponse,
protobufPackage,
SignInfo
Service,
SignInfo,
VerificationMethod
} from "@cheqd/ts-proto/cheqd/did/v2"
import { EncodeObject, GeneratedType } from "@cosmjs/proto-signing"

export const typeUrlMsgCreateDidDoc = `/${protobufPackage}.MsgCreateDidDoc`
export const typeUrlMsgCreateDidDocResponse = `/${protobufPackage}.MsgCreateDidDocResponse`
export const typeUrlMsgUpdateDidDoc = `/${protobufPackage}.MsgUpdateDidDoc`
export const typeUrlMsgUpdateDidDocResponse = `/${protobufPackage}.MsgUpdateDidDocResponse`
export const typeUrlMsgDeactivateDidDoc = `/${protobufPackage}.MsgDeactivateDidDoc`
export const typeUrlMsgDeactivateDidDocResponse = `/${protobufPackage}.MsgDeactivateDidDocResponse`
import { v4 } from "uuid"
import { Coin } from "cosmjs-types/cosmos/base/v1beta1/coin";
import { Int53 } from "@cosmjs/math";

export const protobufLiterals = {
MsgCreateDidDoc: "MsgCreateDidDoc",
MsgCreateDidDocResponse: "MsgCreateDidDocResponse",
MsgUpdateDidDoc: "MsgUpdateDidDoc",
MsgUpdateDidDocResponse: "MsgUpdateDidDocResponse",
MsgDeactivateDidDoc: "MsgDeactivateDidDoc",
MsgDeactivateDidDocResponse: "MsgDeactivateDidDocResponse",
} as const
export const typeUrlMsgCreateDidDoc = `/${protobufPackage}.${protobufLiterals.MsgCreateDidDoc}`
export const typeUrlMsgCreateDidDocResponse = `/${protobufPackage}.${protobufLiterals.MsgCreateDidDocResponse}`
export const typeUrlMsgUpdateDidDoc = `/${protobufPackage}.${protobufLiterals.MsgUpdateDidDoc}`
export const typeUrlMsgUpdateDidDocResponse = `/${protobufPackage}.${protobufLiterals.MsgUpdateDidDocResponse}`
export const typeUrlMsgDeactivateDidDoc = `/${protobufPackage}.${protobufLiterals.MsgDeactivateDidDoc}`
export const typeUrlMsgDeactivateDidDocResponse = `/${protobufPackage}.${protobufLiterals.MsgDeactivateDidDocResponse}`

export interface MsgCreateDidDocEncodeObject extends EncodeObject {
readonly typeUrl: typeof typeUrlMsgCreateDidDoc,
Expand Down Expand Up @@ -87,6 +102,14 @@ export class DIDModule extends AbstractCheqdSDKModule {
[typeUrlMsgDeactivateDidDocResponse, MsgDeactivateDidDocResponse],
]

static readonly baseMinimalDenom = 'ncheq' as const

static readonly fees = {
DefaultCreateDidFee: { amount: '50000000000', denom: DIDModule.baseMinimalDenom } as const,
DefaultUpdateDidFee: { amount: '25000000000', denom: DIDModule.baseMinimalDenom } as const,
DefaultDeactivateDidFee: { amount: '10000000000', denom: DIDModule.baseMinimalDenom } as const,
} as const

constructor(signer: CheqdSigningStargateClient) {
super(signer)
this.methods = {
Expand All @@ -100,12 +123,36 @@ export class DIDModule extends AbstractCheqdSDKModule {
return DIDModule.registryTypes
}

async createDidTx(signInputs: ISignInputs[] | SignInfo[], didPayload: Partial<MsgCreateDidPayload>, address: string, fee: DidStdFee | 'auto' | number, memo?: string, context?: IContext): Promise<DeliverTxResponse> {
async createDidTx(signInputs: ISignInputs[] | SignInfo[], didPayload: DIDDocument, address: string, fee: DidStdFee | 'auto' | number, memo?: string, versionId?: string, context?: IContext): Promise<DeliverTxResponse> {
if (!this._signer) {
this._signer = context!.sdk!.signer
}

const payload = MsgCreateDidPayload.transformPayload(didPayload)
if (!versionId || versionId === '') {
versionId = v4()
}

const { valid, error, protobufVerificationMethod, protobufService } = await DIDModule.validateSpecCompliantPayload(didPayload)

if (!valid) {
throw new Error(`DID payload is not spec compliant: ${error}`)
}

const payload = MsgCreateDidDocPayload.fromPartial({
context: <string[]>didPayload?.['@context'],
id: didPayload.id,
controller: <string[]>didPayload.controller,
verificationMethod: protobufVerificationMethod,
authentication: <string[]>didPayload.authentication,
assertionMethod: <string[]>didPayload.assertionMethod,
capabilityInvocation: <string[]>didPayload.capabilityInvocation,
capabilityDelegation: <string[]>didPayload.capabilityDelegation,
keyAgreement: <string[]>didPayload.keyAgreement,
service: protobufService,
alsoKnownAs: <string[]>didPayload.alsoKnownAs,
versionId: versionId
})

let signatures: SignInfo[]
if(ISignInputs.isSignInput(signInputs)) {
signatures = await this._signer.signCreateDidTx(signInputs, payload)
Expand All @@ -131,12 +178,35 @@ export class DIDModule extends AbstractCheqdSDKModule {
)
}

async updateDidTx(signInputs: ISignInputs[] | SignInfo[], didPayload: Partial<MsgUpdateDidPayload>, address: string, fee: DidStdFee | 'auto' | number, memo?: string, context?: IContext): Promise<DeliverTxResponse> {
async updateDidTx(signInputs: ISignInputs[] | SignInfo[], didPayload: DIDDocument, address: string, fee: DidStdFee | 'auto' | number, memo?: string, versionId?: string, context?: IContext): Promise<DeliverTxResponse> {
if (!this._signer) {
this._signer = context!.sdk!.signer
}

const payload = MsgCreateDidPayload.transformPayload(didPayload)
if (!versionId || versionId === '') {
versionId = v4()
}

const { valid, error, protobufVerificationMethod, protobufService } = await DIDModule.validateSpecCompliantPayload(didPayload)

if (!valid) {
throw new Error(`DID payload is not spec compliant: ${error}`)
}

const payload = MsgUpdateDidDocPayload.fromPartial({
context: <string[]>didPayload?.['@context'],
id: didPayload.id,
controller: <string[]>didPayload.controller,
verificationMethod: protobufVerificationMethod,
authentication: <string[]>didPayload.authentication,
assertionMethod: <string[]>didPayload.assertionMethod,
capabilityInvocation: <string[]>didPayload.capabilityInvocation,
capabilityDelegation: <string[]>didPayload.capabilityDelegation,
keyAgreement: <string[]>didPayload.keyAgreement,
service: protobufService,
alsoKnownAs: <string[]>didPayload.alsoKnownAs,
versionId: versionId
})
let signatures: SignInfo[]
if(ISignInputs.isSignInput(signInputs)) {
signatures = await this._signer.signUpdateDidTx(signInputs, payload)
Expand All @@ -162,15 +232,29 @@ export class DIDModule extends AbstractCheqdSDKModule {
)
}

async deactivateDidTx(signInputs: ISignInputs[] | SignInfo[], didPayload: MsgDeactivateDidPayload, address: string, fee: DidStdFee | 'auto' | number, memo?: string, context?: IContext): Promise<DeliverTxResponse> {
async deactivateDidTx(signInputs: ISignInputs[] | SignInfo[], didPayload: DIDDocument, address: string, fee: DidStdFee | 'auto' | number, memo?: string, versionId?: string, context?: IContext): Promise<DeliverTxResponse> {
if (!this._signer) {
this._signer = context!.sdk!.signer
}

const payload = MsgDeactivateDidDocPayload.fromPartial({id: didPayload.id, versionId: didPayload.versionId})
if (!versionId || versionId === '') {
versionId = v4()
}

const { valid, error, protobufVerificationMethod } = await DIDModule.validateSpecCompliantPayload(didPayload)

if (!valid) {
throw new Error(`DID payload is not spec compliant: ${error}`)
}

const payload = MsgDeactivateDidDocPayload.fromPartial({
id: didPayload.id,
versionId: versionId
})

let signatures: SignInfo[]
if(ISignInputs.isSignInput(signInputs)) {
signatures = await this._signer.signDeactivateDidTx(signInputs, payload, didPayload.verificationMethod.map((e)=>VerificationMethodPayload.transformPayload(e)))
signatures = await this._signer.signDeactivateDidTx(signInputs, payload, protobufVerificationMethod!)
} else {
signatures = signInputs
}
Expand All @@ -192,6 +276,95 @@ export class DIDModule extends AbstractCheqdSDKModule {
memo
)
}

static async validateSpecCompliantPayload(didDocument: DIDDocument): Promise<SpecValidationResult> {
// id is required, validated on both compile and runtime
if (!didDocument?.id) return { valid: false, error: 'id is required' }

// verificationMethod is required
if (!didDocument?.verificationMethod) return { valid: false, error: 'verificationMethod is required' }

// verificationMethod must be an array
if (!Array.isArray(didDocument?.verificationMethod)) return { valid: false, error: 'verificationMethod must be an array' }

// verificationMethod types must be supported
const protoVerificationMethod = didDocument.verificationMethod.map((vm) => {
switch (vm?.type) {
case VerificationMethods.Ed255192020:
if (!vm?.publicKeyMultibase) throw new Error('publicKeyMultibase is required')

return VerificationMethod.fromPartial({
id: vm.id,
controller: vm.controller,
verificationMethodType: VerificationMethods.Ed255192020,
verificationMaterial: vm.publicKeyMultibase,
})
case VerificationMethods.JWK:
if (!vm?.publicKeyJwk) throw new Error('publicKeyJwk is required')

return VerificationMethod.fromPartial({
id: vm.id,
controller: vm.controller,
verificationMethodType: VerificationMethods.JWK,
verificationMaterial: JSON.stringify(vm.publicKeyJwk),
})
case VerificationMethods.Ed255192018:
if (!vm?.publicKeyBase58) throw new Error('publicKeyBase58 is required')

return VerificationMethod.fromPartial({
id: vm.id,
controller: vm.controller,
verificationMethodType: VerificationMethods.Ed255192018,
verificationMaterial: vm.publicKeyBase58,
})
default:
throw new Error('Unsupported verificationMethod type')
}
})

const protoService = didDocument?.service?.map((s) => {
return Service.fromPartial({
id: s?.id,
serviceType: s?.type,
serviceEndpoint: <string[]>s?.serviceEndpoint,
})
})

return { valid: true, protobufVerificationMethod: protoVerificationMethod, protobufService: protoService } as SpecValidationResult
}

static async generateCreateDidDocFees(feePayer: string, granter?: string): Promise<DidStdFee> {
return {
amount: [
DIDModule.fees.DefaultCreateDidFee
],
gas: '360000',
payer: feePayer,
granter: granter
} as DidStdFee
}

static async generateUpdateDidDocFees(feePayer: string, granter?: string): Promise<DidStdFee> {
return {
amount: [
DIDModule.fees.DefaultUpdateDidFee
],
gas: '360000',
payer: feePayer,
granter: granter
} as DidStdFee
}

static async generateDeactivateDidDocFees(feePayer: string, granter?: string): Promise<DidStdFee> {
return {
amount: [
DIDModule.fees.DefaultDeactivateDidFee
],
gas: '360000',
payer: feePayer,
granter: granter
} as DidStdFee
}
}

export type MinimalImportableDIDModule = MinimalImportableCheqdSDKModule<DIDModule>
Expand Down
Loading

0 comments on commit 1ef3a07

Please sign in to comment.