@cheqd/sdk 1.5.0-develop.2 → 2.0.0-develop.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/types.ts CHANGED
@@ -1,8 +1,8 @@
1
+ import { Service as ProtobufService, VerificationMethod as ProtobufVerificationMethod } from "@cheqd/ts-proto/cheqd/did/v2"
1
2
  import { CheqdSDK } from "."
2
3
  import { Coin } from "@cosmjs/proto-signing"
3
4
  import { Signer } from "did-jwt"
4
- import { MsgCreateDidDocPayload, MsgDeactivateDidDocPayload, MsgUpdateDidDocPayload, VerificationMethod, Service } from "@cheqd/ts-proto/cheqd/did/v2"
5
- import { DeepPartial, Exact } from "cosmjs-types/confio/proofs"
5
+ export { DIDDocument, VerificationMethod, Service, ServiceEndpoint, JsonWebKey } from "did-resolver"
6
6
 
7
7
  export enum CheqdNetwork {
8
8
  Mainnet = 'mainnet',
@@ -19,6 +19,13 @@ export interface IContext {
19
19
  sdk: CheqdSDK
20
20
  }
21
21
 
22
+ export type SpecValidationResult = {
23
+ valid: boolean
24
+ error?: string
25
+ protobufVerificationMethod?: ProtobufVerificationMethod[]
26
+ protobufService?: ProtobufService[]
27
+ }
28
+
22
29
  export enum VerificationMethods {
23
30
  Ed255192020 = 'Ed25519VerificationKey2020',
24
31
  Ed255192018 = 'Ed25519VerificationKey2018',
@@ -40,12 +47,6 @@ export interface ISignInputs {
40
47
  privateKeyHex: string
41
48
  }
42
49
 
43
- export const ISignInputs = {
44
- isSignInput(object: Object[]): object is ISignInputs[] {
45
- return object.some((x)=> 'privateKeyHex' in x)
46
- }
47
- }
48
-
49
50
  export interface IKeyPair {
50
51
  publicKey: string
51
52
  privateKey: string
@@ -77,151 +78,8 @@ export interface DidStdFee {
77
78
  granter?: string
78
79
  }
79
80
 
80
- export interface MsgDeactivateDidPayload extends MsgDeactivateDidDocPayload {
81
- verificationMethod: VerificationMethodPayload[]
82
- }
83
-
84
- export interface MsgCreateDidPayload extends Omit<MsgCreateDidDocPayload, 'verificationMethod' | 'service'> {
85
- verificationMethod: VerificationMethodPayload[]
86
- service: ServicePayload[]
87
- }
88
-
89
- export const MsgCreateDidPayload = {
90
- transformPayload<I extends Exact<DeepPartial<MsgCreateDidPayload>, I>>(message: I): MsgCreateDidDocPayload {
91
- const obj: any = {};
92
- if (message.context) {
93
- obj.context = message.context
94
- } else {
95
- obj.context = [];
96
- }
97
- message.id !== undefined && (obj.id = message.id);
98
- if (message.controller) {
99
- obj.controller = message.controller
100
- }
101
- if (message.verificationMethod) {
102
- obj.verificationMethod = message.verificationMethod.map((e) => e ? VerificationMethodPayload.transformPayload(e) : undefined);
103
- }
104
- if (message.authentication) {
105
- obj.authentication = message.authentication
106
- }
107
- if (message.assertionMethod) {
108
- obj.assertionMethod = message.assertionMethod
109
- }
110
- if (message.capabilityInvocation) {
111
- obj.capabilityInvocation = message.capabilityInvocation
112
- }
113
- if (message.capabilityDelegation) {
114
- obj.capabilityDelegation = message.capabilityDelegation
115
- }
116
- if (message.keyAgreement) {
117
- obj.keyAgreement = message.keyAgreement
118
- }
119
- if (message.alsoKnownAs) {
120
- obj.alsoKnownAs = message.alsoKnownAs
121
- }
122
- if (message.service) {
123
- obj.service = message.service.map((e) => e ? {id: e.id, serviceEndpoint: e.serviceEndpoint, serviceType: e.type} as Service : undefined);
124
- }
125
- message.versionId !== undefined && (obj.versionId = message.versionId);
126
- return MsgCreateDidDocPayload.fromPartial(obj);
127
- },
128
-
129
- fromPartial<I extends Exact<DeepPartial<MsgCreateDidPayload>, I>>(object: I): MsgCreateDidPayload {
130
- const message = createBaseMsgCreateDidPayload();
131
- message.context = object.context?.map((e) => e) || [];
132
- message.id = object.id ?? "";
133
- message.controller = object.controller?.map((e) => e) || [];
134
- message.verificationMethod = object.verificationMethod?.map((e) => VerificationMethodPayload.fromPartial(e)) || [];
135
- message.authentication = object.authentication?.map((e) => e) || [];
136
- message.assertionMethod = object.assertionMethod?.map((e) => e) || [];
137
- message.capabilityInvocation = object.capabilityInvocation?.map((e) => e) || [];
138
- message.capabilityDelegation = object.capabilityDelegation?.map((e) => e) || [];
139
- message.keyAgreement = object.keyAgreement?.map((e) => e) || [];
140
- message.alsoKnownAs = object.alsoKnownAs?.map((e) => e) || [];
141
- message.service = object.service?.map((e) => ServicePayload.fromPartial(e)) || [];
142
- message.versionId = object.versionId ?? "";
143
- return message;
144
- },
145
-
146
- }
147
-
148
- function createBaseMsgCreateDidPayload(): MsgCreateDidPayload {
149
- return {
150
- context: [],
151
- id: "",
152
- controller: [],
153
- verificationMethod: [],
154
- authentication: [],
155
- assertionMethod: [],
156
- capabilityInvocation: [],
157
- capabilityDelegation: [],
158
- keyAgreement: [],
159
- alsoKnownAs: [],
160
- service: [],
161
- versionId: "",
162
- };
163
- }
164
-
165
- export interface VerificationMethodPayload {
166
- id: string;
167
- type: string;
168
- controller: string;
169
- publicKeyBase58?: string;
170
- publicKeyMultibase?: string;
171
- publicKeyJWK?: any;
172
- }
173
-
174
- export const VerificationMethodPayload = {
175
- fromPartial<I extends Exact<DeepPartial<VerificationMethodPayload>, I>>(object: I): VerificationMethodPayload {
176
- const message = createBaseVerificationMethod();
177
- message.id = object.id ?? "";
178
- message.type = object.type ?? "";
179
- message.controller = object.controller ?? "";
180
- if(object.publicKeyMultibase) {
181
- message.publicKeyMultibase = object.publicKeyMultibase;
182
- } else if (object.publicKeyBase58) {
183
- message.publicKeyBase58 = object.publicKeyBase58;
184
- } else if (object.publicKeyJWK) {
185
- message.publicKeyJWK = object.publicKeyJWK;
186
- }
187
- return message;
188
- },
189
-
190
- transformPayload<I extends Exact<DeepPartial<VerificationMethodPayload>, I>>(payload: I): VerificationMethod {
191
- return {
192
- id: payload.id ?? "",
193
- controller: payload.controller ?? "",
194
- verificationMethodType: payload.type ?? "",
195
- verificationMaterial: payload.publicKeyBase58 || payload.publicKeyMultibase || JSON.stringify(payload.publicKeyJWK) || ""
196
- } as VerificationMethod
197
- }
198
- }
199
-
200
- function createBaseVerificationMethod(): VerificationMethodPayload {
201
- return { id: "", type: "", controller: "" };
202
- }
203
-
204
- export interface ServicePayload {
205
- id: string;
206
- type: string;
207
- serviceEndpoint: string[];
208
- }
209
-
210
- export const ServicePayload = {
211
- fromPartial<I extends Exact<DeepPartial<ServicePayload>, I>>(object: I): ServicePayload {
212
- const message = createBaseService();
213
- message.id = object.id ?? "";
214
- message.type = object.type ?? "";
215
- message.serviceEndpoint = object.serviceEndpoint?.map((e) => e) || [];
216
- return message;
217
- },
218
- }
219
-
220
- function createBaseService(): ServicePayload {
221
- return { id: "", type: "", serviceEndpoint: [] };
222
- }
223
-
224
- export interface MsgUpdateDidPayload extends Omit<MsgUpdateDidDocPayload, 'verificationMethod' | 'service'> {
225
- verificationMethod: VerificationMethodPayload[]
226
- service: ServicePayload[]
227
- }
81
+ export const ISignInputs = {
82
+ isSignInput(object: Object[]): object is ISignInputs[] {
83
+ return object.some((x)=> 'privateKeyHex' in x)
84
+ }
85
+ }
package/src/utils.ts CHANGED
@@ -8,10 +8,11 @@ import {
8
8
  TVerificationKey,
9
9
  TVerificationKeyPrefix,
10
10
  CheqdNetwork,
11
- IVerificationKeys,
12
- MsgCreateDidPayload,
13
- VerificationMethodPayload,
14
- MsgUpdateDidPayload
11
+ IVerificationKeys,
12
+ VerificationMethod,
13
+ DIDDocument,
14
+ SpecValidationResult,
15
+ JsonWebKey,
15
16
  } from "./types"
16
17
  import { fromString, toString } from 'uint8arrays'
17
18
  import { bases } from "multiformats/basics"
@@ -19,6 +20,10 @@ import { base64ToBytes } from "did-jwt"
19
20
  import { generateKeyPair, generateKeyPairFromSeed, KeyPair } from '@stablelib/ed25519'
20
21
  import { v4 } from 'uuid'
21
22
  import { createHash } from 'crypto'
23
+ import {
24
+ VerificationMethod as ProtoVerificationMethod,
25
+ Service as ProtoService,
26
+ } from "@cheqd/ts-proto/cheqd/did/v2"
22
27
 
23
28
  export type TImportableEd25519Key = {
24
29
  publicKeyHex: string
@@ -27,16 +32,13 @@ export type TImportableEd25519Key = {
27
32
  type: "Ed25519"
28
33
  }
29
34
 
30
- // multicodec ed25519-pub header as varint
31
- const MULTICODEC_ED25519_PUB_HEADER = new Uint8Array([0xed, 0x01]);
32
-
33
- export type IdentifierPayload = Partial<MsgCreateDidPayload> | Partial<MsgUpdateDidPayload>
35
+ const MULTICODEC_ED25519_HEADER = new Uint8Array([0xed, 0x01]);
34
36
 
35
37
  export function isEqualKeyValuePair(kv1: IKeyValuePair[], kv2: IKeyValuePair[]): boolean {
36
38
  return kv1.every((item, index) => item.key === kv2[index].key && item.value === kv2[index].value)
37
39
  }
38
40
 
39
- export function createSignInputsFromImportableEd25519Key(key: TImportableEd25519Key, verificationMethod: VerificationMethodPayload[]): ISignInputs {
41
+ export function createSignInputsFromImportableEd25519Key(key: TImportableEd25519Key, verificationMethod: VerificationMethod[]): ISignInputs {
40
42
  if (verificationMethod?.length === 0) throw new Error('No verification methods provided')
41
43
 
42
44
  const publicKey = fromString(key.publicKeyHex, 'hex')
@@ -44,14 +46,13 @@ export function createSignInputsFromImportableEd25519Key(key: TImportableEd25519
44
46
  for(const method of verificationMethod) {
45
47
  switch (method?.type) {
46
48
  case VerificationMethods.Ed255192020:
47
- const publicKeyMultibase = _encodeMbKey(MULTICODEC_ED25519_PUB_HEADER, publicKey)
49
+ const publicKeyMultibase = toMultibaseRaw(publicKey)
48
50
  if (method.publicKeyMultibase === publicKeyMultibase) {
49
51
  return {
50
52
  verificationMethodId: method.id,
51
53
  privateKeyHex: key.privateKeyHex
52
54
  }
53
55
  }
54
-
55
56
  case VerificationMethods.Ed255192018:
56
57
  const publicKeyBase58 = bases['base58btc'].encode(publicKey).slice(1)
57
58
  if (method.publicKeyBase58 === publicKeyBase58) {
@@ -60,20 +61,17 @@ export function createSignInputsFromImportableEd25519Key(key: TImportableEd25519
60
61
  privateKeyHex: key.privateKeyHex
61
62
  }
62
63
  }
63
-
64
64
  case VerificationMethods.JWK:
65
- const publicKeyJWK: any = {
65
+ const publicKeyJwk: JsonWebKey = {
66
66
  crv: 'Ed25519',
67
67
  kty: 'OKP',
68
68
  x: toString( publicKey, 'base64url' )
69
69
  }
70
- if (JSON.stringify(method.publicKeyJWK) === JSON.stringify(publicKeyJWK)) {
70
+ if (JSON.stringify(method.publicKeyJwk) === JSON.stringify(publicKeyJwk)) {
71
71
  return {
72
72
  verificationMethodId: method.id,
73
73
  privateKeyHex: key.privateKeyHex
74
74
  }
75
- } else {
76
- throw new Error(`JWK not matching ${method.publicKeyJWK}, ${publicKeyJWK}`)
77
75
  }
78
76
  }
79
77
  }
@@ -105,7 +103,7 @@ export function createVerificationKeys(publicKey: string, algo: MethodSpecificId
105
103
  let methodSpecificId: TMethodSpecificId
106
104
  let didUrl: IVerificationKeys['didUrl']
107
105
 
108
- publicKey = isBase64(publicKey) ? publicKey : toString(fromString(publicKey, 'hex'), 'base64')
106
+ publicKey = publicKey.length == 43 ? publicKey : toString(fromString(publicKey, 'hex'), 'base64')
109
107
  switch (algo) {
110
108
  case MethodSpecificIdAlgo.Base58:
111
109
  methodSpecificId = bases['base58btc'].encode(base64ToBytes(publicKey))
@@ -128,9 +126,7 @@ export function createVerificationKeys(publicKey: string, algo: MethodSpecificId
128
126
  }
129
127
  }
130
128
 
131
- const isBase64 = (value: string) => /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(value);
132
-
133
- export function createDidVerificationMethod(verificationMethodTypes: VerificationMethods[], verificationKeys: IVerificationKeys[]): VerificationMethodPayload[] {
129
+ export function createDidVerificationMethod(verificationMethodTypes: VerificationMethods[], verificationKeys: IVerificationKeys[]): VerificationMethod[] {
134
130
  return verificationMethodTypes.map((type, _) => {
135
131
  switch (type) {
136
132
  case VerificationMethods.Ed255192020:
@@ -138,61 +134,110 @@ export function createDidVerificationMethod(verificationMethodTypes: Verificatio
138
134
  id: verificationKeys[_].keyId,
139
135
  type,
140
136
  controller: verificationKeys[_].didUrl,
141
- publicKeyMultibase: _encodeMbKey(MULTICODEC_ED25519_PUB_HEADER, base64ToBytes(verificationKeys[_].publicKey))
142
- }
143
-
137
+ publicKeyMultibase: toMultibaseRaw(base64ToBytes(verificationKeys[_].publicKey))
138
+ } as VerificationMethod
144
139
  case VerificationMethods.Ed255192018:
145
140
  return {
146
141
  id: verificationKeys[_].keyId,
147
142
  type,
148
143
  controller: verificationKeys[_].didUrl,
149
144
  publicKeyBase58: verificationKeys[_].methodSpecificId.slice(1)
150
- }
151
-
145
+ } as VerificationMethod
152
146
  case VerificationMethods.JWK:
153
147
  return {
154
148
  id: verificationKeys[_].keyId,
155
149
  type,
156
150
  controller: verificationKeys[_].didUrl,
157
- publicKeyJWK: {
151
+ publicKeyJwk: {
158
152
  crv: 'Ed25519',
159
153
  kty: 'OKP',
160
154
  x: toString( fromString( verificationKeys[_].publicKey, 'base64pad' ), 'base64url' )
161
155
  }
162
- }
156
+ } as VerificationMethod
163
157
  }
164
158
  }) ?? []
165
159
  }
166
160
 
167
- export function createDidPayload(verificationMethods: VerificationMethodPayload[], verificationKeys: IVerificationKeys[]): MsgCreateDidPayload {
161
+ export function createDidPayload(verificationMethods: VerificationMethod[], verificationKeys: IVerificationKeys[]): DIDDocument {
168
162
  if (!verificationMethods || verificationMethods.length === 0)
169
163
  throw new Error('No verification methods provided')
170
164
  if (!verificationKeys || verificationKeys.length === 0)
171
165
  throw new Error('No verification keys provided')
172
166
 
173
167
  const did = verificationKeys[0].didUrl
174
- return MsgCreateDidPayload.fromPartial(
175
- {
168
+ return {
176
169
  id: did,
177
170
  controller: verificationKeys.map(key => key.didUrl),
178
171
  verificationMethod: verificationMethods,
179
172
  authentication: verificationKeys.map(key => key.keyId),
180
- versionId: v4()
173
+ } as DIDDocument
174
+ }
175
+
176
+ export function validateSpecCompliantPayload(didDocument: DIDDocument): SpecValidationResult {
177
+ // id is required, validated on both compile and runtime
178
+ if (!didDocument?.id) return { valid: false, error: 'id is required' }
179
+
180
+ // verificationMethod is required
181
+ if (!didDocument?.verificationMethod) return { valid: false, error: 'verificationMethod is required' }
182
+
183
+ // verificationMethod must be an array
184
+ if (!Array.isArray(didDocument?.verificationMethod)) return { valid: false, error: 'verificationMethod must be an array' }
185
+
186
+ // verificationMethod types must be supported
187
+ const protoVerificationMethod = didDocument.verificationMethod.map((vm) => {
188
+ switch (vm?.type) {
189
+ case VerificationMethods.Ed255192020:
190
+ if (!vm.publicKeyMultibase) throw new Error('publicKeyMultibase is required')
191
+
192
+ return ProtoVerificationMethod.fromPartial({
193
+ id: vm.id,
194
+ controller: vm.controller,
195
+ verificationMethodType: VerificationMethods.Ed255192020,
196
+ verificationMaterial: vm.publicKeyMultibase,
197
+ })
198
+ case VerificationMethods.JWK:
199
+ if (!vm.publicKeyJwk) throw new Error('publicKeyJwk is required')
200
+
201
+ return ProtoVerificationMethod.fromPartial({
202
+ id: vm.id,
203
+ controller: vm.controller,
204
+ verificationMethodType: VerificationMethods.JWK,
205
+ verificationMaterial: JSON.stringify(vm.publicKeyJwk),
206
+ })
207
+ case VerificationMethods.Ed255192018:
208
+ if (!vm.publicKeyBase58) throw new Error('publicKeyBase58 is required')
209
+
210
+ return ProtoVerificationMethod.fromPartial({
211
+ id: vm.id,
212
+ controller: vm.controller,
213
+ verificationMethodType: VerificationMethods.Ed255192018,
214
+ verificationMaterial: vm.publicKeyBase58,
215
+ })
216
+ default:
217
+ throw new Error(`Unsupported verificationMethod type: ${vm?.type}`)
181
218
  }
182
- )
219
+ })
220
+
221
+ const protoService = didDocument?.service?.map((s) => {
222
+ return ProtoService.fromPartial({
223
+ id: s?.id,
224
+ serviceType: s?.type,
225
+ serviceEndpoint: <string[]>s?.serviceEndpoint,
226
+ })
227
+ })
228
+
229
+ return { valid: true, protobufVerificationMethod: protoVerificationMethod, protobufService: protoService }
183
230
  }
184
231
 
185
232
  function sha256(message: string) {
186
233
  return createHash('sha256').update(message).digest('hex')
187
234
  }
188
235
 
189
- // encode a multibase base58-btc multicodec key
190
- function _encodeMbKey(header: any, key: Uint8Array) {
191
- const mbKey = new Uint8Array(header.length + key.length);
192
-
193
- mbKey.set(header);
194
- mbKey.set(key, header.length);
195
-
196
- return bases['base58btc'].encode(mbKey);
236
+ function toMultibaseRaw(key: Uint8Array) {
237
+ const multibase = new Uint8Array(MULTICODEC_ED25519_HEADER.length + key.length);
238
+
239
+ multibase.set(MULTICODEC_ED25519_HEADER);
240
+ multibase.set(key, MULTICODEC_ED25519_HEADER.length);
241
+
242
+ return bases['base58btc'].encode(multibase);
197
243
  }
198
-
@@ -1,6 +1,6 @@
1
1
  import { DirectSecp256k1HdWallet, GeneratedType } from '@cosmjs/proto-signing'
2
2
  import { createCheqdSDK, DIDModule, ICheqdSDKOptions, ResourceModule } from '../src/index'
3
- import { exampleCheqdNetwork, faucet } from './testutils.test'
3
+ import { localnet, faucet } from './testutils.test'
4
4
  import { AbstractCheqdSDKModule } from '../src/modules/_'
5
5
  import { CheqdSigningStargateClient } from '../src/signer'
6
6
  import { createDefaultCheqdRegistry } from '../src/registry'
@@ -11,7 +11,7 @@ describe(
11
11
  it('can be instantiated with modules', async () => {
12
12
  const options = {
13
13
  modules: [DIDModule as unknown as AbstractCheqdSDKModule],
14
- rpcUrl: exampleCheqdNetwork.rpcUrl,
14
+ rpcUrl: localnet.rpcUrl,
15
15
  wallet: await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic)
16
16
  } as ICheqdSDKOptions
17
17
  const cheqdSDK = await createCheqdSDK(options)
@@ -26,7 +26,7 @@ describe(
26
26
  })
27
27
 
28
28
  it('should use module methods', async () => {
29
- const rpcUrl = exampleCheqdNetwork.rpcUrl
29
+ const rpcUrl = localnet.rpcUrl
30
30
  const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic)
31
31
 
32
32
  class TestModule extends AbstractCheqdSDKModule {
@@ -56,7 +56,6 @@ describe(
56
56
  const doSomething = await cheqdSDK.doSomething()
57
57
  expect(doSomething).toBe('did something')
58
58
 
59
- //@ts-ignore
60
59
  const spy = jest.spyOn(cheqdSDK.methods, 'doSomething')
61
60
  //@ts-ignore
62
61
  await cheqdSDK.doSomething()
@@ -66,7 +65,7 @@ describe(
66
65
  it('should instantiate registry from passed modules', async () => {
67
66
  const options = {
68
67
  modules: [DIDModule as unknown as AbstractCheqdSDKModule],
69
- rpcUrl: exampleCheqdNetwork.rpcUrl,
68
+ rpcUrl: localnet.rpcUrl,
70
69
  wallet: await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic)
71
70
  } as ICheqdSDKOptions
72
71
  const cheqdSDK = await createCheqdSDK(options)
@@ -80,7 +79,7 @@ describe(
80
79
  it('should instantiate registry from multiple passed modules', async () => {
81
80
  const options = {
82
81
  modules: [DIDModule as unknown as AbstractCheqdSDKModule, ResourceModule as unknown as AbstractCheqdSDKModule],
83
- rpcUrl: exampleCheqdNetwork.rpcUrl,
82
+ rpcUrl: localnet.rpcUrl,
84
83
  wallet: await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic)
85
84
  } as ICheqdSDKOptions
86
85
  const cheqdSDK = await createCheqdSDK(options)