@cheqd/sdk-esm 5.3.7 → 5.4.0-develop.2
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/build/cjs/src/index.d.ts +142 -0
- package/build/cjs/src/index.d.ts.map +1 -0
- package/build/cjs/src/index.js +184 -0
- package/build/cjs/src/index.js.map +1 -0
- package/build/cjs/src/modules/_.d.ts +81 -0
- package/build/cjs/src/modules/_.d.ts.map +1 -0
- package/build/cjs/src/modules/_.js +93 -0
- package/build/cjs/src/modules/_.js.map +1 -0
- package/build/cjs/src/modules/did.d.ts +488 -0
- package/build/cjs/src/modules/did.d.ts.map +1 -0
- package/build/cjs/src/modules/did.js +1255 -0
- package/build/cjs/src/modules/did.js.map +1 -0
- package/build/cjs/src/modules/feeabstraction.d.ts +429 -0
- package/build/cjs/src/modules/feeabstraction.d.ts.map +1 -0
- package/build/cjs/src/modules/feeabstraction.js +474 -0
- package/build/cjs/src/modules/feeabstraction.js.map +1 -0
- package/build/cjs/src/modules/feemarket.d.ts +244 -0
- package/build/cjs/src/modules/feemarket.d.ts.map +1 -0
- package/build/cjs/src/modules/feemarket.js +297 -0
- package/build/cjs/src/modules/feemarket.js.map +1 -0
- package/build/cjs/src/modules/oracle.d.ts +563 -0
- package/build/cjs/src/modules/oracle.d.ts.map +1 -0
- package/build/cjs/src/modules/oracle.js +784 -0
- package/build/cjs/src/modules/oracle.js.map +1 -0
- package/build/cjs/src/modules/resource.d.ts +330 -0
- package/build/cjs/src/modules/resource.d.ts.map +1 -0
- package/build/cjs/src/modules/resource.js +556 -0
- package/build/cjs/src/modules/resource.js.map +1 -0
- package/build/cjs/src/querier.d.ts +62 -0
- package/build/cjs/src/querier.d.ts.map +1 -0
- package/build/cjs/src/querier.js +87 -0
- package/build/cjs/src/querier.js.map +1 -0
- package/build/cjs/src/registry.d.ts +18 -0
- package/build/cjs/src/registry.d.ts.map +1 -0
- package/build/cjs/src/registry.js +23 -0
- package/build/cjs/src/registry.js.map +1 -0
- package/build/cjs/src/signer.d.ts +250 -0
- package/build/cjs/src/signer.d.ts.map +1 -0
- package/build/cjs/src/signer.js +617 -0
- package/build/cjs/src/signer.js.map +1 -0
- package/build/cjs/src/types.d.ts +221 -0
- package/build/cjs/src/types.d.ts.map +1 -0
- package/build/cjs/src/types.js.map +1 -0
- package/build/cjs/src/utils.d.ts +233 -0
- package/build/cjs/src/utils.d.ts.map +1 -0
- package/build/cjs/src/utils.js +571 -0
- package/build/cjs/src/utils.js.map +1 -0
- package/build/{index.d.ts → esm/src/index.d.ts} +7 -3
- package/build/esm/src/index.d.ts.map +1 -0
- package/build/{index.js → esm/src/index.js} +3 -1
- package/build/esm/src/index.js.map +1 -0
- package/build/esm/src/modules/_.d.ts.map +1 -0
- package/build/esm/src/modules/_.js.map +1 -0
- package/build/{modules → esm/src/modules}/did.d.ts +109 -7
- package/build/esm/src/modules/did.d.ts.map +1 -0
- package/build/{modules → esm/src/modules}/did.js +220 -8
- package/build/esm/src/modules/did.js.map +1 -0
- package/build/esm/src/modules/feeabstraction.d.ts.map +1 -0
- package/build/esm/src/modules/feeabstraction.js.map +1 -0
- package/build/esm/src/modules/feemarket.d.ts.map +1 -0
- package/build/esm/src/modules/feemarket.js.map +1 -0
- package/build/esm/src/modules/oracle.d.ts +563 -0
- package/build/esm/src/modules/oracle.d.ts.map +1 -0
- package/build/esm/src/modules/oracle.js +784 -0
- package/build/esm/src/modules/oracle.js.map +1 -0
- package/build/{modules → esm/src/modules}/resource.d.ts +132 -6
- package/build/esm/src/modules/resource.d.ts.map +1 -0
- package/build/esm/src/modules/resource.js +556 -0
- package/build/esm/src/modules/resource.js.map +1 -0
- package/build/esm/src/querier.d.ts.map +1 -0
- package/build/esm/src/querier.js.map +1 -0
- package/build/esm/src/registry.d.ts.map +1 -0
- package/build/esm/src/registry.js.map +1 -0
- package/build/esm/src/signer.d.ts.map +1 -0
- package/build/esm/src/signer.js.map +1 -0
- package/build/{types → esm/src}/types.d.ts +27 -1
- package/build/esm/src/types.d.ts.map +1 -0
- package/build/esm/src/types.js +43 -0
- package/build/esm/src/types.js.map +1 -0
- package/build/esm/src/utils.d.ts.map +1 -0
- package/build/esm/src/utils.js.map +1 -0
- package/build/types/cjs/src/index.d.ts +142 -0
- package/build/types/cjs/src/index.d.ts.map +1 -0
- package/build/types/cjs/src/modules/_.d.ts +81 -0
- package/build/types/cjs/src/modules/_.d.ts.map +1 -0
- package/build/types/cjs/src/modules/did.d.ts +488 -0
- package/build/types/cjs/src/modules/did.d.ts.map +1 -0
- package/build/types/cjs/src/modules/feeabstraction.d.ts +429 -0
- package/build/types/cjs/src/modules/feeabstraction.d.ts.map +1 -0
- package/build/types/cjs/src/modules/feemarket.d.ts +244 -0
- package/build/types/cjs/src/modules/feemarket.d.ts.map +1 -0
- package/build/types/cjs/src/modules/oracle.d.ts +563 -0
- package/build/types/cjs/src/modules/oracle.d.ts.map +1 -0
- package/build/types/cjs/src/modules/resource.d.ts +330 -0
- package/build/types/cjs/src/modules/resource.d.ts.map +1 -0
- package/build/types/cjs/src/querier.d.ts +62 -0
- package/build/types/cjs/src/querier.d.ts.map +1 -0
- package/build/types/cjs/src/registry.d.ts +18 -0
- package/build/types/cjs/src/registry.d.ts.map +1 -0
- package/build/types/cjs/src/signer.d.ts +250 -0
- package/build/types/cjs/src/signer.d.ts.map +1 -0
- package/build/types/cjs/src/types.d.ts +221 -0
- package/build/types/cjs/src/types.d.ts.map +1 -0
- package/build/types/cjs/src/utils.d.ts +233 -0
- package/build/types/cjs/src/utils.d.ts.map +1 -0
- package/build/types/{index.d.ts → esm/src/index.d.ts} +7 -3
- package/build/types/esm/src/index.d.ts.map +1 -0
- package/build/types/esm/src/modules/_.d.ts.map +1 -0
- package/build/types/{modules → esm/src/modules}/did.d.ts +109 -7
- package/build/types/esm/src/modules/did.d.ts.map +1 -0
- package/build/types/esm/src/modules/feeabstraction.d.ts.map +1 -0
- package/build/types/esm/src/modules/feemarket.d.ts.map +1 -0
- package/build/types/esm/src/modules/oracle.d.ts +563 -0
- package/build/types/esm/src/modules/oracle.d.ts.map +1 -0
- package/build/types/{modules → esm/src/modules}/resource.d.ts +132 -6
- package/build/types/esm/src/modules/resource.d.ts.map +1 -0
- package/build/types/esm/src/querier.d.ts.map +1 -0
- package/build/types/esm/src/registry.d.ts.map +1 -0
- package/build/types/esm/src/signer.d.ts.map +1 -0
- package/build/{types.d.ts → types/esm/src/types.d.ts} +27 -1
- package/build/types/esm/src/types.d.ts.map +1 -0
- package/build/types/esm/src/utils.d.ts.map +1 -0
- package/package.json +2 -2
- package/build/index.d.ts.map +0 -1
- package/build/index.js.map +0 -1
- package/build/modules/_.d.ts.map +0 -1
- package/build/modules/_.js.map +0 -1
- package/build/modules/did.d.ts.map +0 -1
- package/build/modules/did.js.map +0 -1
- package/build/modules/feeabstraction.d.ts.map +0 -1
- package/build/modules/feeabstraction.js.map +0 -1
- package/build/modules/feemarket.d.ts.map +0 -1
- package/build/modules/feemarket.js.map +0 -1
- package/build/modules/resource.d.ts.map +0 -1
- package/build/modules/resource.js +0 -297
- package/build/modules/resource.js.map +0 -1
- package/build/querier.d.ts.map +0 -1
- package/build/querier.js.map +0 -1
- package/build/registry.d.ts.map +0 -1
- package/build/registry.js.map +0 -1
- package/build/signer.d.ts.map +0 -1
- package/build/signer.js.map +0 -1
- package/build/types/index.d.ts.map +0 -1
- package/build/types/modules/_.d.ts.map +0 -1
- package/build/types/modules/did.d.ts.map +0 -1
- package/build/types/modules/feeabstraction.d.ts.map +0 -1
- package/build/types/modules/feemarket.d.ts.map +0 -1
- package/build/types/modules/resource.d.ts.map +0 -1
- package/build/types/querier.d.ts.map +0 -1
- package/build/types/registry.d.ts.map +0 -1
- package/build/types/signer.d.ts.map +0 -1
- package/build/types/types.d.ts.map +0 -1
- package/build/types/utils.d.ts.map +0 -1
- package/build/types.d.ts.map +0 -1
- package/build/types.js.map +0 -1
- package/build/utils.d.ts.map +0 -1
- package/build/utils.js.map +0 -1
- /package/build/{types.js → cjs/src/types.js} +0 -0
- /package/build/{modules → esm/src/modules}/_.d.ts +0 -0
- /package/build/{modules → esm/src/modules}/_.js +0 -0
- /package/build/{modules → esm/src/modules}/feeabstraction.d.ts +0 -0
- /package/build/{modules → esm/src/modules}/feeabstraction.js +0 -0
- /package/build/{modules → esm/src/modules}/feemarket.d.ts +0 -0
- /package/build/{modules → esm/src/modules}/feemarket.js +0 -0
- /package/build/{querier.d.ts → esm/src/querier.d.ts} +0 -0
- /package/build/{querier.js → esm/src/querier.js} +0 -0
- /package/build/{registry.d.ts → esm/src/registry.d.ts} +0 -0
- /package/build/{registry.js → esm/src/registry.js} +0 -0
- /package/build/{signer.d.ts → esm/src/signer.d.ts} +0 -0
- /package/build/{signer.js → esm/src/signer.js} +0 -0
- /package/build/{types → esm/src}/utils.d.ts +0 -0
- /package/build/{utils.js → esm/src/utils.js} +0 -0
- /package/build/types/{modules → esm/src/modules}/_.d.ts +0 -0
- /package/build/types/{modules → esm/src/modules}/feeabstraction.d.ts +0 -0
- /package/build/types/{modules → esm/src/modules}/feemarket.d.ts +0 -0
- /package/build/types/{querier.d.ts → esm/src/querier.d.ts} +0 -0
- /package/build/types/{registry.d.ts → esm/src/registry.d.ts} +0 -0
- /package/build/types/{signer.d.ts → esm/src/signer.d.ts} +0 -0
- /package/build/{utils.d.ts → types/esm/src/utils.d.ts} +0 -0
|
@@ -0,0 +1,1255 @@
|
|
|
1
|
+
import { createPagination, createProtobufRpcClient } from '@cosmjs/stargate-cjs';
|
|
2
|
+
import { AbstractCheqdSDKModule } from './_';
|
|
3
|
+
import { ISignInputs, VerificationMethods, } from '../types';
|
|
4
|
+
import { MsgCreateDidDoc, MsgCreateDidDocPayload, MsgCreateDidDocResponse, MsgDeactivateDidDoc, MsgDeactivateDidDocPayload, MsgDeactivateDidDocResponse, MsgUpdateDidDoc, MsgUpdateDidDocPayload, MsgUpdateDidDocResponse, protobufPackage, QueryClientImpl, VerificationMethod, } from '@cheqd/ts-proto-cjs/cheqd/did/v2/index';
|
|
5
|
+
import { parseCoins } from '@cosmjs/proto-signing-cjs';
|
|
6
|
+
import { v4 } from 'uuid-cjs';
|
|
7
|
+
import { assert } from '@cosmjs/utils-cjs';
|
|
8
|
+
import { denormalizeService, normalizeAuthentication, normalizeController, normalizeService } from '../utils';
|
|
9
|
+
import { defaultOracleExtensionKey, MovingAverages, WMAStrategies } from './oracle';
|
|
10
|
+
import { Coin } from 'cosmjs-types/cosmos/base/v1beta1/coin';
|
|
11
|
+
/** Default extension key for DID-related query operations */
|
|
12
|
+
export const defaultDidExtensionKey = 'did';
|
|
13
|
+
/**
|
|
14
|
+
* Standard W3C and DID-related context URIs used in DID documents.
|
|
15
|
+
* These contexts define the semantic meaning of properties in DID documents.
|
|
16
|
+
*/
|
|
17
|
+
export const contexts = {
|
|
18
|
+
/** W3C DID Core v1 context */
|
|
19
|
+
W3CDIDv1: 'https://www.w3.org/ns/did/v1',
|
|
20
|
+
/** Ed25519 Signature Suite 2020 context */
|
|
21
|
+
W3CSuiteEd255192020: 'https://w3id.org/security/suites/ed25519-2020/v1',
|
|
22
|
+
/** Ed25519 Signature Suite 2018 context */
|
|
23
|
+
W3CSuiteEd255192018: 'https://w3id.org/security/suites/ed25519-2018/v1',
|
|
24
|
+
/** JSON Web Signature Suite 2020 context */
|
|
25
|
+
W3CSuiteJws2020: 'https://w3id.org/security/suites/jws-2020/v1',
|
|
26
|
+
/** Linked Domains context for domain verification */
|
|
27
|
+
LinkedDomainsContext: 'https://identity.foundation/.well-known/did-configuration/v1',
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Protobuf message type literals for DID operations.
|
|
31
|
+
* Used for consistent message type identification across the module.
|
|
32
|
+
*/
|
|
33
|
+
export const protobufLiterals = {
|
|
34
|
+
/** Create DID document message type */
|
|
35
|
+
MsgCreateDidDoc: 'MsgCreateDidDoc',
|
|
36
|
+
/** Create DID document response message type */
|
|
37
|
+
MsgCreateDidDocResponse: 'MsgCreateDidDocResponse',
|
|
38
|
+
/** Update DID document message type */
|
|
39
|
+
MsgUpdateDidDoc: 'MsgUpdateDidDoc',
|
|
40
|
+
/** Update DID document response message type */
|
|
41
|
+
MsgUpdateDidDocResponse: 'MsgUpdateDidDocResponse',
|
|
42
|
+
/** Deactivate DID document message type */
|
|
43
|
+
MsgDeactivateDidDoc: 'MsgDeactivateDidDoc',
|
|
44
|
+
/** Deactivate DID document response message type */
|
|
45
|
+
MsgDeactivateDidDocResponse: 'MsgDeactivateDidDocResponse',
|
|
46
|
+
};
|
|
47
|
+
/** Type URL for MsgCreateDidDoc messages */
|
|
48
|
+
export const typeUrlMsgCreateDidDoc = `/${protobufPackage}.${protobufLiterals.MsgCreateDidDoc}`;
|
|
49
|
+
/** Type URL for MsgCreateDidDocResponse messages */
|
|
50
|
+
export const typeUrlMsgCreateDidDocResponse = `/${protobufPackage}.${protobufLiterals.MsgCreateDidDocResponse}`;
|
|
51
|
+
/** Type URL for MsgUpdateDidDoc messages */
|
|
52
|
+
export const typeUrlMsgUpdateDidDoc = `/${protobufPackage}.${protobufLiterals.MsgUpdateDidDoc}`;
|
|
53
|
+
/** Type URL for MsgUpdateDidDocResponse messages */
|
|
54
|
+
export const typeUrlMsgUpdateDidDocResponse = `/${protobufPackage}.${protobufLiterals.MsgUpdateDidDocResponse}`;
|
|
55
|
+
/** Type URL for MsgDeactivateDidDoc messages */
|
|
56
|
+
export const typeUrlMsgDeactivateDidDoc = `/${protobufPackage}.${protobufLiterals.MsgDeactivateDidDoc}`;
|
|
57
|
+
/** Type URL for MsgDeactivateDidDocResponse messages */
|
|
58
|
+
export const typeUrlMsgDeactivateDidDocResponse = `/${protobufPackage}.${protobufLiterals.MsgDeactivateDidDocResponse}`;
|
|
59
|
+
/**
|
|
60
|
+
* Type guard function to check if an object is a MsgCreateDidDocEncodeObject.
|
|
61
|
+
*
|
|
62
|
+
* @param obj - EncodeObject to check
|
|
63
|
+
* @returns True if the object is a MsgCreateDidDocEncodeObject
|
|
64
|
+
*/
|
|
65
|
+
export function isMsgCreateDidDocEncodeObject(obj) {
|
|
66
|
+
return obj.typeUrl === typeUrlMsgCreateDidDoc;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Type guard function to check if an object is a MsgUpdateDidDocEncodeObject.
|
|
70
|
+
*
|
|
71
|
+
* @param obj - EncodeObject to check
|
|
72
|
+
* @returns True if the object is a MsgUpdateDidDocEncodeObject
|
|
73
|
+
*/
|
|
74
|
+
export function isMsgUpdateDidDocEncodeObject(obj) {
|
|
75
|
+
return obj.typeUrl === typeUrlMsgUpdateDidDoc;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Type guard function to check if an object is a MsgDeactivateDidDocEncodeObject.
|
|
79
|
+
*
|
|
80
|
+
* @param obj - EncodeObject to check
|
|
81
|
+
* @returns True if the object is a MsgDeactivateDidDocEncodeObject
|
|
82
|
+
*/
|
|
83
|
+
export function isMsgDeactivateDidDocEncodeObject(obj) {
|
|
84
|
+
return obj.typeUrl === typeUrlMsgDeactivateDidDoc;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Type guard function to check if an object is a MsgCreateDidDocResponseEncodeObject.
|
|
88
|
+
*
|
|
89
|
+
* @param obj - EncodeObject to check
|
|
90
|
+
* @returns True if the object is a MsgCreateDidDocResponseEncodeObject
|
|
91
|
+
*/
|
|
92
|
+
export function MsgCreateDidDocResponseEncodeObject(obj) {
|
|
93
|
+
return obj.typeUrl === typeUrlMsgCreateDidDocResponse;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Type guard function to check if an object is a MsgUpdateDidDocEncodeObject.
|
|
97
|
+
*
|
|
98
|
+
* @param obj - EncodeObject to check
|
|
99
|
+
* @returns True if the object is a MsgUpdateDidDocEncodeObject
|
|
100
|
+
*/
|
|
101
|
+
export function MsgUpdateDidDocEncodeObject(obj) {
|
|
102
|
+
return obj.typeUrl === typeUrlMsgUpdateDidDoc;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Type guard function to check if an object is a MsgUpdateDidDocResponseEncodeObject.
|
|
106
|
+
*
|
|
107
|
+
* @param obj - EncodeObject to check
|
|
108
|
+
* @returns True if the object is a MsgUpdateDidDocResponseEncodeObject
|
|
109
|
+
*/
|
|
110
|
+
export function MsgUpdateDidDocResponseEncodeObject(obj) {
|
|
111
|
+
return obj.typeUrl === typeUrlMsgUpdateDidDocResponse;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Type guard function to check if an object is a MsgDeactivateDidDocEncodeObject.
|
|
115
|
+
*
|
|
116
|
+
* @param obj - EncodeObject to check
|
|
117
|
+
* @returns True if the object is a MsgDeactivateDidDocEncodeObject
|
|
118
|
+
*/
|
|
119
|
+
export function MsgDeactivateDidDocEncodeObject(obj) {
|
|
120
|
+
return obj.typeUrl === typeUrlMsgDeactivateDidDoc;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Type guard function to check if an object is a MsgDeactivateDidDocResponseEncodeObject.
|
|
124
|
+
*
|
|
125
|
+
* @param obj - EncodeObject to check
|
|
126
|
+
* @returns True if the object is a MsgDeactivateDidDocResponseEncodeObject
|
|
127
|
+
*/
|
|
128
|
+
export function MsgDeactiveDidDocResponseEncodeObject(obj) {
|
|
129
|
+
return obj.typeUrl === typeUrlMsgUpdateDidDocResponse;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Sets up the DID extension for the querier client.
|
|
133
|
+
* Creates and configures the DID-specific query methods.
|
|
134
|
+
*
|
|
135
|
+
* @param base - Base QueryClient to extend
|
|
136
|
+
* @returns Configured DID extension with query methods
|
|
137
|
+
*/
|
|
138
|
+
export const setupDidExtension = (base) => {
|
|
139
|
+
const rpc = createProtobufRpcClient(base);
|
|
140
|
+
const queryService = new QueryClientImpl(rpc);
|
|
141
|
+
return {
|
|
142
|
+
[defaultDidExtensionKey]: {
|
|
143
|
+
didDoc: async (id) => {
|
|
144
|
+
const { value } = await queryService.DidDoc({ id });
|
|
145
|
+
assert(value);
|
|
146
|
+
return value;
|
|
147
|
+
},
|
|
148
|
+
didDocVersion: async (id, versionId) => {
|
|
149
|
+
const { value } = await queryService.DidDocVersion({ id, version: versionId });
|
|
150
|
+
assert(value);
|
|
151
|
+
return value;
|
|
152
|
+
},
|
|
153
|
+
allDidDocVersionsMetadata: async (id, paginationKey) => {
|
|
154
|
+
const response = await queryService.AllDidDocVersionsMetadata({
|
|
155
|
+
id,
|
|
156
|
+
pagination: createPagination(paginationKey),
|
|
157
|
+
});
|
|
158
|
+
return response;
|
|
159
|
+
},
|
|
160
|
+
params: async () => {
|
|
161
|
+
const response = await queryService.Params({});
|
|
162
|
+
assert(response.params);
|
|
163
|
+
return response;
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
/**
|
|
169
|
+
* DID Module class providing comprehensive DID document management functionality.
|
|
170
|
+
* Handles creation, updates, deactivation, and querying of DID documents on the Cheqd blockchain.
|
|
171
|
+
*/
|
|
172
|
+
export class DIDModule extends AbstractCheqdSDKModule {
|
|
173
|
+
// @ts-expect-error underlying type `GeneratedType` is intentionally wider
|
|
174
|
+
static registryTypes = [
|
|
175
|
+
[typeUrlMsgCreateDidDoc, MsgCreateDidDoc],
|
|
176
|
+
[typeUrlMsgCreateDidDocResponse, MsgCreateDidDocResponse],
|
|
177
|
+
[typeUrlMsgUpdateDidDoc, MsgUpdateDidDoc],
|
|
178
|
+
[typeUrlMsgUpdateDidDocResponse, MsgUpdateDidDocResponse],
|
|
179
|
+
[typeUrlMsgDeactivateDidDoc, MsgDeactivateDidDoc],
|
|
180
|
+
[typeUrlMsgDeactivateDidDocResponse, MsgDeactivateDidDocResponse],
|
|
181
|
+
];
|
|
182
|
+
/** Base denomination for Cheqd network transactions */
|
|
183
|
+
static baseMinimalDenom = 'ncheq';
|
|
184
|
+
/** Base denomination in USD for Cheqd network transactions */
|
|
185
|
+
static baseUsdDenom = 'usd';
|
|
186
|
+
/** Default slippage tolerance in base points (BPS) */
|
|
187
|
+
static defaultSlippageBps = 500n;
|
|
188
|
+
/**
|
|
189
|
+
* Standard fee amounts for DID operations.
|
|
190
|
+
* These represent the default costs for different DID document operations.
|
|
191
|
+
*/
|
|
192
|
+
static fees = {
|
|
193
|
+
/** Default fee for creating a new DID document */
|
|
194
|
+
DefaultCreateDidDocFee: { amount: '50000000000', denom: DIDModule.baseMinimalDenom },
|
|
195
|
+
/** Default fee for updating an existing DID document */
|
|
196
|
+
DefaultUpdateDidDocFee: { amount: '25000000000', denom: DIDModule.baseMinimalDenom },
|
|
197
|
+
/** Default fee for deactivating a DID document */
|
|
198
|
+
DefaultDeactivateDidDocFee: { amount: '10000000000', denom: DIDModule.baseMinimalDenom },
|
|
199
|
+
/** Default fee for creating a new DID document in USD */
|
|
200
|
+
DefaultCreateDidDocFeeUSD: { amount: '2000000000000000000', denom: DIDModule.baseUsdDenom },
|
|
201
|
+
/** Default fee for updating an existing DID document in USD */
|
|
202
|
+
DefaultUpdateDidDocFeeUSD: { amount: '1000000000000000000', denom: DIDModule.baseUsdDenom },
|
|
203
|
+
/** Default fee for deactivating a DID document in USD */
|
|
204
|
+
DefaultDeactivateDidDocFeeUSD: { amount: '400000000000000000', denom: DIDModule.baseUsdDenom },
|
|
205
|
+
};
|
|
206
|
+
/**
|
|
207
|
+
* Standard gas limits for DID operations.
|
|
208
|
+
* These represent the default gas limits for different DID document operations.
|
|
209
|
+
*/
|
|
210
|
+
static gasLimits = {
|
|
211
|
+
/** Gas limit for creating a new DID document */
|
|
212
|
+
CreateDidDocGasLimit: '360000',
|
|
213
|
+
/** Gas limit for updating an existing DID document */
|
|
214
|
+
UpdateDidDocGasLimit: '360000',
|
|
215
|
+
/** Gas limit for deactivating a DID document */
|
|
216
|
+
DeactivateDidDocGasLimit: '360000',
|
|
217
|
+
};
|
|
218
|
+
/** Querier extension setup function for DID operations */
|
|
219
|
+
static querierExtensionSetup = setupDidExtension;
|
|
220
|
+
/** Querier instance with DID extension capabilities */
|
|
221
|
+
querier;
|
|
222
|
+
/**
|
|
223
|
+
* Constructs a new DID module instance.
|
|
224
|
+
*
|
|
225
|
+
* @param signer - Signing client for blockchain transactions
|
|
226
|
+
* @param querier - Querier client with DID extension for data retrieval
|
|
227
|
+
*/
|
|
228
|
+
constructor(signer, querier) {
|
|
229
|
+
super(signer, querier);
|
|
230
|
+
this.querier = querier;
|
|
231
|
+
this.methods = {
|
|
232
|
+
createDidDocTx: this.createDidDocTx.bind(this),
|
|
233
|
+
updateDidDocTx: this.updateDidDocTx.bind(this),
|
|
234
|
+
deactivateDidDocTx: this.deactivateDidDocTx.bind(this),
|
|
235
|
+
queryDidDoc: this.queryDidDoc.bind(this),
|
|
236
|
+
queryDidDocVersion: this.queryDidDocVersion.bind(this),
|
|
237
|
+
queryAllDidDocVersionsMetadata: this.queryAllDidDocVersionsMetadata.bind(this),
|
|
238
|
+
queryParams: this.queryParams.bind(this),
|
|
239
|
+
generateCreateDidDocFees: this.generateCreateDidDocFees.bind(this),
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Gets the registry types for DID message encoding/decoding.
|
|
244
|
+
*
|
|
245
|
+
* @returns Iterable of [typeUrl, GeneratedType] pairs for the registry
|
|
246
|
+
*/
|
|
247
|
+
getRegistryTypes() {
|
|
248
|
+
return DIDModule.registryTypes;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Gets the querier extension setup for DID operations.
|
|
252
|
+
*
|
|
253
|
+
* @returns Query extension setup function for DID functionality
|
|
254
|
+
*/
|
|
255
|
+
getQuerierExtensionSetup() {
|
|
256
|
+
return DIDModule.querierExtensionSetup;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Creates a new DID document transaction on the blockchain.
|
|
260
|
+
* Validates the DID payload and authentication before submission.
|
|
261
|
+
*
|
|
262
|
+
* @param signInputs - Signing inputs or pre-computed signatures for the transaction
|
|
263
|
+
* @param didPayload - DID document payload to create
|
|
264
|
+
* @param address - Address of the account submitting the transaction
|
|
265
|
+
* @param fee - Transaction fee configuration or 'auto' for automatic calculation
|
|
266
|
+
* @param memo - Optional transaction memo
|
|
267
|
+
* @param versionId - Optional version identifier for the DID document
|
|
268
|
+
* @param feeOptions - Optional fee options for the transaction
|
|
269
|
+
* @param context - Optional SDK context for accessing clients
|
|
270
|
+
* @returns Promise resolving to the transaction response
|
|
271
|
+
* @throws Error if DID payload is not spec compliant or authentication is invalid
|
|
272
|
+
*/
|
|
273
|
+
async createDidDocTx(signInputs, didPayload, address, fee, memo, versionId, feeOptions, context) {
|
|
274
|
+
if (!this._signer) {
|
|
275
|
+
this._signer = context.sdk.signer;
|
|
276
|
+
}
|
|
277
|
+
if (!this.querier) {
|
|
278
|
+
this.querier = context.sdk.querier;
|
|
279
|
+
}
|
|
280
|
+
if (!versionId || versionId === '') {
|
|
281
|
+
versionId = v4();
|
|
282
|
+
}
|
|
283
|
+
const { valid, error, protobufVerificationMethod, protobufService } = await DIDModule.validateSpecCompliantPayload(didPayload);
|
|
284
|
+
if (!valid) {
|
|
285
|
+
throw new Error(`DID payload is not spec compliant: ${error}`);
|
|
286
|
+
}
|
|
287
|
+
const { valid: authenticationValid, error: authenticationError } = await DIDModule.validateAuthenticationAgainstSignatures(didPayload, signInputs, this.querier);
|
|
288
|
+
if (!authenticationValid) {
|
|
289
|
+
throw new Error(`DID authentication is not valid: ${authenticationError}`);
|
|
290
|
+
}
|
|
291
|
+
const payload = MsgCreateDidDocPayload.fromPartial({
|
|
292
|
+
context: didPayload?.['@context'],
|
|
293
|
+
id: didPayload.id,
|
|
294
|
+
controller: didPayload.controller,
|
|
295
|
+
verificationMethod: protobufVerificationMethod,
|
|
296
|
+
authentication: didPayload.authentication,
|
|
297
|
+
assertionMethod: didPayload.assertionMethod,
|
|
298
|
+
capabilityInvocation: didPayload.capabilityInvocation,
|
|
299
|
+
capabilityDelegation: didPayload.capabilityDelegation,
|
|
300
|
+
keyAgreement: didPayload.keyAgreement,
|
|
301
|
+
service: protobufService,
|
|
302
|
+
alsoKnownAs: didPayload.alsoKnownAs,
|
|
303
|
+
versionId: versionId,
|
|
304
|
+
});
|
|
305
|
+
let signatures;
|
|
306
|
+
if (ISignInputs.isSignInput(signInputs)) {
|
|
307
|
+
signatures = await this._signer.signCreateDidDocTx(signInputs, payload);
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
signatures = signInputs;
|
|
311
|
+
}
|
|
312
|
+
const value = {
|
|
313
|
+
payload,
|
|
314
|
+
signatures,
|
|
315
|
+
};
|
|
316
|
+
const createDidMsg = {
|
|
317
|
+
typeUrl: typeUrlMsgCreateDidDoc,
|
|
318
|
+
value,
|
|
319
|
+
};
|
|
320
|
+
if (address === '') {
|
|
321
|
+
address = (await context.sdk.options.wallet.getAccounts())[0].address;
|
|
322
|
+
}
|
|
323
|
+
if (!fee) {
|
|
324
|
+
fee = await this.generateCreateDidDocFees(address, undefined, feeOptions, context);
|
|
325
|
+
}
|
|
326
|
+
return this._signer.signAndBroadcast(address, [createDidMsg], fee, memo);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Updates an existing DID document transaction on the blockchain.
|
|
330
|
+
* Validates the updated DID payload and handles key rotation scenarios.
|
|
331
|
+
*
|
|
332
|
+
* @param signInputs - Signing inputs or pre-computed signatures for the transaction
|
|
333
|
+
* @param didPayload - Updated DID document payload
|
|
334
|
+
* @param address - Address of the account submitting the transaction
|
|
335
|
+
* @param fee - Transaction fee configuration or 'auto' for automatic calculation
|
|
336
|
+
* @param memo - Optional transaction memo
|
|
337
|
+
* @param versionId - Optional version identifier for the updated DID document
|
|
338
|
+
* @param feeOptions - Optional fee options for the transaction
|
|
339
|
+
* @param context - Optional SDK context for accessing clients
|
|
340
|
+
* @returns Promise resolving to the transaction response
|
|
341
|
+
* @throws Error if DID payload is not spec compliant or authentication is invalid
|
|
342
|
+
*/
|
|
343
|
+
async updateDidDocTx(signInputs, didPayload, address, fee, memo, versionId, feeOptions, context) {
|
|
344
|
+
if (!this._signer) {
|
|
345
|
+
this._signer = context.sdk.signer;
|
|
346
|
+
}
|
|
347
|
+
if (!this.querier) {
|
|
348
|
+
this.querier = context.sdk.querier;
|
|
349
|
+
}
|
|
350
|
+
if (!versionId || versionId === '') {
|
|
351
|
+
versionId = v4();
|
|
352
|
+
}
|
|
353
|
+
const { valid, error, protobufVerificationMethod, protobufService } = await DIDModule.validateSpecCompliantPayload(didPayload);
|
|
354
|
+
if (!valid) {
|
|
355
|
+
throw new Error(`DID payload is not spec compliant: ${error}`);
|
|
356
|
+
}
|
|
357
|
+
const { valid: authenticationValid, error: authenticationError, externalControllersDocuments, previousDidDocument, } = await DIDModule.validateAuthenticationAgainstSignaturesKeyRotation(didPayload, signInputs, this.querier);
|
|
358
|
+
if (!authenticationValid) {
|
|
359
|
+
throw new Error(`DID authentication is not valid: ${authenticationError}`);
|
|
360
|
+
}
|
|
361
|
+
const payload = MsgUpdateDidDocPayload.fromPartial({
|
|
362
|
+
context: didPayload?.['@context'],
|
|
363
|
+
id: didPayload.id,
|
|
364
|
+
controller: didPayload.controller,
|
|
365
|
+
verificationMethod: protobufVerificationMethod,
|
|
366
|
+
authentication: didPayload.authentication,
|
|
367
|
+
assertionMethod: didPayload.assertionMethod,
|
|
368
|
+
capabilityInvocation: didPayload.capabilityInvocation,
|
|
369
|
+
capabilityDelegation: didPayload.capabilityDelegation,
|
|
370
|
+
keyAgreement: didPayload.keyAgreement,
|
|
371
|
+
service: protobufService,
|
|
372
|
+
alsoKnownAs: didPayload.alsoKnownAs,
|
|
373
|
+
versionId: versionId,
|
|
374
|
+
});
|
|
375
|
+
let signatures;
|
|
376
|
+
if (ISignInputs.isSignInput(signInputs)) {
|
|
377
|
+
signatures = await this._signer.signUpdateDidDocTx(signInputs, payload, externalControllersDocuments, previousDidDocument);
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
signatures = signInputs;
|
|
381
|
+
}
|
|
382
|
+
const value = {
|
|
383
|
+
payload,
|
|
384
|
+
signatures,
|
|
385
|
+
};
|
|
386
|
+
const updateDidMsg = {
|
|
387
|
+
typeUrl: typeUrlMsgUpdateDidDoc,
|
|
388
|
+
value,
|
|
389
|
+
};
|
|
390
|
+
if (address === '') {
|
|
391
|
+
address = (await context.sdk.options.wallet.getAccounts())[0].address;
|
|
392
|
+
}
|
|
393
|
+
if (!fee) {
|
|
394
|
+
fee = await this.generateUpdateDidDocFees(address, undefined, feeOptions, context);
|
|
395
|
+
}
|
|
396
|
+
return this._signer.signAndBroadcast(address, [updateDidMsg], fee, memo);
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Deactivates an existing DID document transaction on the blockchain.
|
|
400
|
+
* Validates authentication and creates a deactivation transaction.
|
|
401
|
+
*
|
|
402
|
+
* @param signInputs - Signing inputs or pre-computed signatures for the transaction
|
|
403
|
+
* @param didPayload - DID document payload containing the ID to deactivate
|
|
404
|
+
* @param address - Address of the account submitting the transaction
|
|
405
|
+
* @param fee - Transaction fee configuration or 'auto' for automatic calculation
|
|
406
|
+
* @param memo - Optional transaction memo
|
|
407
|
+
* @param versionId - Optional version identifier for the deactivation
|
|
408
|
+
* @param feeOptions - Optional fee options for the transaction
|
|
409
|
+
* @param context - Optional SDK context for accessing clients
|
|
410
|
+
* @returns Promise resolving to the transaction response
|
|
411
|
+
* @throws Error if DID payload is not spec compliant or authentication is invalid
|
|
412
|
+
*/
|
|
413
|
+
async deactivateDidDocTx(signInputs, didPayload, address, fee, memo, versionId, feeOptions, context) {
|
|
414
|
+
if (!this._signer) {
|
|
415
|
+
this._signer = context.sdk.signer;
|
|
416
|
+
}
|
|
417
|
+
if (!versionId || versionId === '') {
|
|
418
|
+
versionId = v4();
|
|
419
|
+
}
|
|
420
|
+
const { valid, error, protobufVerificationMethod } = await DIDModule.validateSpecCompliantPayload(didPayload);
|
|
421
|
+
if (!valid) {
|
|
422
|
+
throw new Error(`DID payload is not spec compliant: ${error}`);
|
|
423
|
+
}
|
|
424
|
+
const { valid: authenticationValid, error: authenticationError } = await DIDModule.validateAuthenticationAgainstSignatures(didPayload, signInputs, this.querier);
|
|
425
|
+
if (!authenticationValid) {
|
|
426
|
+
throw new Error(`DID authentication is not valid: ${authenticationError}`);
|
|
427
|
+
}
|
|
428
|
+
const payload = MsgDeactivateDidDocPayload.fromPartial({
|
|
429
|
+
id: didPayload.id,
|
|
430
|
+
versionId: versionId,
|
|
431
|
+
});
|
|
432
|
+
let signatures;
|
|
433
|
+
if (ISignInputs.isSignInput(signInputs)) {
|
|
434
|
+
signatures = await this._signer.signDeactivateDidDocTx(signInputs, payload, protobufVerificationMethod);
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
signatures = signInputs;
|
|
438
|
+
}
|
|
439
|
+
const value = {
|
|
440
|
+
payload,
|
|
441
|
+
signatures,
|
|
442
|
+
};
|
|
443
|
+
const deactivateDidMsg = {
|
|
444
|
+
typeUrl: typeUrlMsgDeactivateDidDoc,
|
|
445
|
+
value,
|
|
446
|
+
};
|
|
447
|
+
if (address === '') {
|
|
448
|
+
address = (await context.sdk.options.wallet.getAccounts())[0].address;
|
|
449
|
+
}
|
|
450
|
+
if (!fee) {
|
|
451
|
+
fee = await this.generateDeactivateDidDocFees(address, undefined, feeOptions, context);
|
|
452
|
+
}
|
|
453
|
+
return this._signer.signAndBroadcast(address, [deactivateDidMsg], fee, memo);
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Queries a DID document by its identifier.
|
|
457
|
+
* Retrieves the latest version of the DID document with metadata.
|
|
458
|
+
*
|
|
459
|
+
* @param id - DID identifier to query
|
|
460
|
+
* @param context - Optional SDK context for accessing clients
|
|
461
|
+
* @returns Promise resolving to the DID document with metadata
|
|
462
|
+
*/
|
|
463
|
+
async queryDidDoc(id, context) {
|
|
464
|
+
if (!this.querier) {
|
|
465
|
+
this.querier = context.sdk.querier;
|
|
466
|
+
}
|
|
467
|
+
const { didDoc, metadata } = await this.querier[defaultDidExtensionKey].didDoc(id);
|
|
468
|
+
return {
|
|
469
|
+
didDocument: await DIDModule.toSpecCompliantPayload(didDoc),
|
|
470
|
+
didDocumentMetadata: await DIDModule.toSpecCompliantMetadata(metadata),
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Queries a specific version of a DID document by its identifier and version ID.
|
|
475
|
+
*
|
|
476
|
+
* @param id - DID identifier to query
|
|
477
|
+
* @param versionId - Specific version identifier to retrieve
|
|
478
|
+
* @param context - Optional SDK context for accessing clients
|
|
479
|
+
* @returns Promise resolving to the DID document version with metadata
|
|
480
|
+
*/
|
|
481
|
+
async queryDidDocVersion(id, versionId, context) {
|
|
482
|
+
if (!this.querier) {
|
|
483
|
+
this.querier = context.sdk.querier;
|
|
484
|
+
}
|
|
485
|
+
const { didDoc, metadata } = await this.querier[defaultDidExtensionKey].didDocVersion(id, versionId);
|
|
486
|
+
return {
|
|
487
|
+
didDocument: await DIDModule.toSpecCompliantPayload(didDoc),
|
|
488
|
+
didDocumentMetadata: await DIDModule.toSpecCompliantMetadata(metadata),
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Queries metadata for all versions of a DID document.
|
|
493
|
+
* Retrieves version history information for a specific DID.
|
|
494
|
+
*
|
|
495
|
+
* @param id - DID identifier to query version metadata for
|
|
496
|
+
* @param context - Optional SDK context for accessing clients
|
|
497
|
+
* @returns Promise resolving to array of version metadata and pagination info
|
|
498
|
+
*/
|
|
499
|
+
async queryAllDidDocVersionsMetadata(id, context) {
|
|
500
|
+
if (!this.querier) {
|
|
501
|
+
this.querier = context.sdk.querier;
|
|
502
|
+
}
|
|
503
|
+
const { versions, pagination } = await this.querier[defaultDidExtensionKey].allDidDocVersionsMetadata(id);
|
|
504
|
+
return {
|
|
505
|
+
didDocumentVersionsMetadata: await Promise.all(versions.map(async (m) => await DIDModule.toSpecCompliantMetadata(m))),
|
|
506
|
+
pagination,
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Queries the DID module parameters from the blockchain.
|
|
511
|
+
* @param context - Optional SDK context for accessing clients
|
|
512
|
+
* @returns Promise resolving to the DID module parameters
|
|
513
|
+
*/
|
|
514
|
+
async queryParams(context) {
|
|
515
|
+
if (!this.querier) {
|
|
516
|
+
this.querier = context.sdk.querier;
|
|
517
|
+
}
|
|
518
|
+
return this.querier[defaultDidExtensionKey].params();
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Generates oracle-powered fees for creating a DID document.
|
|
522
|
+
*
|
|
523
|
+
* @param feePayer - Address of the account that will pay the transaction fees
|
|
524
|
+
* @param granter - Optional address of the account granting fee payment permissions
|
|
525
|
+
* @param feeOptions - Options for fetching oracle fees
|
|
526
|
+
* @param context - Optional SDK context for accessing clients
|
|
527
|
+
* @returns Promise resolving to the fee configuration for DID document creation with oracle fees
|
|
528
|
+
*/
|
|
529
|
+
async generateCreateDidDocFees(feePayer, granter, feeOptions, context) {
|
|
530
|
+
if (!this.querier) {
|
|
531
|
+
this.querier = context.sdk.querier;
|
|
532
|
+
}
|
|
533
|
+
// fetch fee parameters from the DID module
|
|
534
|
+
const feeParams = await this.queryParams(context);
|
|
535
|
+
// get the price range for the create operation
|
|
536
|
+
const priceRange = await this.getPriceRangeFromParams(feeParams, 'create', feeOptions);
|
|
537
|
+
// calculate the oracle fee amount based on the price range and options
|
|
538
|
+
return {
|
|
539
|
+
amount: [await this.calculateOracleFeeAmount(priceRange, feeOptions, context)],
|
|
540
|
+
gas: feeOptions?.gasLimit || DIDModule.gasLimits.CreateDidDocGasLimit,
|
|
541
|
+
payer: feePayer,
|
|
542
|
+
granter,
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Generates oracle-powered fees for updating a DID document.
|
|
547
|
+
*
|
|
548
|
+
* @param feePayer - Address of the account that will pay the transaction fees
|
|
549
|
+
* @param granter - Optional address of the account granting fee payment permissions
|
|
550
|
+
* @param feeOptions - Options for fetching oracle fees
|
|
551
|
+
* @param context - Optional SDK context for accessing clients
|
|
552
|
+
* @returns Promise resolving to the fee configuration for DID document update with oracle fees
|
|
553
|
+
*/
|
|
554
|
+
async generateUpdateDidDocFees(feePayer, granter, fetchOptions, context) {
|
|
555
|
+
if (!this.querier) {
|
|
556
|
+
this.querier = context.sdk.querier;
|
|
557
|
+
}
|
|
558
|
+
// fetch fee parameters from the DID module
|
|
559
|
+
const feeParams = await this.queryParams(context);
|
|
560
|
+
// get the price range for the update operation
|
|
561
|
+
const priceRange = await this.getPriceRangeFromParams(feeParams, 'update', fetchOptions);
|
|
562
|
+
// calculate the oracle fee amount based on the price range and options
|
|
563
|
+
return {
|
|
564
|
+
amount: [await this.calculateOracleFeeAmount(priceRange, fetchOptions, context)],
|
|
565
|
+
gas: fetchOptions?.gasLimit || DIDModule.gasLimits.UpdateDidDocGasLimit,
|
|
566
|
+
payer: feePayer,
|
|
567
|
+
granter,
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
/** Generates oracle-powered fees for deactivating a DID document.
|
|
571
|
+
*
|
|
572
|
+
* @param feePayer - Address of the account that will pay the transaction fees
|
|
573
|
+
* @param granter - Optional address of the account granting fee payment permissions
|
|
574
|
+
* @param feeOptions - Options for fetching oracle fees
|
|
575
|
+
* @param context - Optional SDK context for accessing clients
|
|
576
|
+
* @returns Promise resolving to the fee configuration for DID document deactivation with oracle fees
|
|
577
|
+
*/
|
|
578
|
+
async generateDeactivateDidDocFees(feePayer, granter, feeOptions, context) {
|
|
579
|
+
if (!this.querier) {
|
|
580
|
+
this.querier = context.sdk.querier;
|
|
581
|
+
}
|
|
582
|
+
// fetch fee parameters from the DID module
|
|
583
|
+
const feeParams = await this.queryParams(context);
|
|
584
|
+
// get the price range for the deactivate operation
|
|
585
|
+
const priceRange = await this.getPriceRangeFromParams(feeParams, 'deactivate', feeOptions);
|
|
586
|
+
// calculate the oracle fee amount based on the price range and options
|
|
587
|
+
return {
|
|
588
|
+
amount: [await this.calculateOracleFeeAmount(priceRange, feeOptions, context)],
|
|
589
|
+
gas: feeOptions?.gasLimit || DIDModule.gasLimits.DeactivateDidDocGasLimit,
|
|
590
|
+
payer: feePayer,
|
|
591
|
+
granter,
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Gets the fee range for a specific DID operation from the module parameters.
|
|
596
|
+
* @param feeParams - DID module fee parameters
|
|
597
|
+
* @param operation - DID operation type ('create', 'update', 'deactivate')
|
|
598
|
+
* @param feeOptions - Options for fee retrieval
|
|
599
|
+
* @returns Promise resolving to the fee range for the specified operation
|
|
600
|
+
*/
|
|
601
|
+
async getPriceRangeFromParams(feeParams, operation, feeOptions) {
|
|
602
|
+
const operationFees = (() => {
|
|
603
|
+
switch (operation) {
|
|
604
|
+
case 'create':
|
|
605
|
+
return feeParams.params?.createDid.find((fee) => fee.denom === (feeOptions?.feeDenom ?? DIDModule.baseUsdDenom));
|
|
606
|
+
case 'update':
|
|
607
|
+
return feeParams.params?.updateDid.find((fee) => fee.denom === (feeOptions?.feeDenom ?? DIDModule.baseUsdDenom));
|
|
608
|
+
case 'deactivate':
|
|
609
|
+
return feeParams.params?.deactivateDid.find((fee) => fee.denom === (feeOptions?.feeDenom ?? DIDModule.baseUsdDenom));
|
|
610
|
+
default:
|
|
611
|
+
throw new Error('Unsupported operation for fee retrieval');
|
|
612
|
+
}
|
|
613
|
+
})();
|
|
614
|
+
if (!operationFees) {
|
|
615
|
+
throw new Error(`Fee parameters not found for operation: ${operation}`);
|
|
616
|
+
}
|
|
617
|
+
return operationFees;
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Calculates the oracle fee amount based on the provided fee range and options.
|
|
621
|
+
* @param feeRange - Fee range for the DID operation
|
|
622
|
+
* @param feeOptions - Options for fee calculation
|
|
623
|
+
* @param context - Optional SDK context for accessing clients
|
|
624
|
+
* @returns Promise resolving to the calculated fee amount as a Coin
|
|
625
|
+
*/
|
|
626
|
+
async calculateOracleFeeAmount(feeRange, feeOptions, context) {
|
|
627
|
+
if (!this.querier) {
|
|
628
|
+
this.querier = context.sdk.querier;
|
|
629
|
+
}
|
|
630
|
+
if (feeRange.denom !== feeOptions?.feeDenom && feeOptions?.feeDenom !== undefined) {
|
|
631
|
+
throw new Error(`Fee denomination mismatch: expected ${feeRange.denom}, got ${feeOptions.feeDenom}`);
|
|
632
|
+
}
|
|
633
|
+
const wantedFeeAmount = feeRange.denom === DIDModule.baseUsdDenom
|
|
634
|
+
? (feeOptions?.wantedAmountUsd ?? DIDModule.isFixedRange(feeRange))
|
|
635
|
+
? feeRange.minAmount
|
|
636
|
+
: feeRange.minAmount
|
|
637
|
+
: feeRange.minAmount;
|
|
638
|
+
// override fee options, if unassigned - case: moving average type
|
|
639
|
+
feeOptions = {
|
|
640
|
+
...feeOptions,
|
|
641
|
+
movingAverageType: feeOptions?.movingAverageType || MovingAverages.WMA,
|
|
642
|
+
};
|
|
643
|
+
// override fee options, if unassigned - case: WMA strategy
|
|
644
|
+
feeOptions = {
|
|
645
|
+
...feeOptions,
|
|
646
|
+
wmaStrategy: feeOptions?.wmaStrategy || feeOptions?.movingAverageType === MovingAverages.WMA
|
|
647
|
+
? WMAStrategies.BALANCED
|
|
648
|
+
: undefined,
|
|
649
|
+
};
|
|
650
|
+
const convertedFeeAmount = feeRange.denom === DIDModule.baseUsdDenom
|
|
651
|
+
? parseCoins((await this.querier[defaultOracleExtensionKey].convertUSDtoCHEQ(wantedFeeAmount, feeOptions?.movingAverageType, feeOptions?.wmaStrategy, feeOptions?.wmaWeights?.map((w) => BigInt(w)))).amount)[0]
|
|
652
|
+
: Coin.fromPartial({ amount: wantedFeeAmount, denom: feeRange.denom });
|
|
653
|
+
return feeOptions?.slippageBps
|
|
654
|
+
? DIDModule.applySlippageToCoin(convertedFeeAmount, feeOptions.slippageBps)
|
|
655
|
+
: convertedFeeAmount;
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Applies slippage to a given coin amount based on the specified basis points.
|
|
659
|
+
* @param coin - Coin amount to apply slippage to
|
|
660
|
+
* @param slippageBps - Slippage in basis points (bps)
|
|
661
|
+
* @returns Coin with adjusted amount after applying slippage
|
|
662
|
+
*/
|
|
663
|
+
static applySlippageToCoin(coin, slippageBps) {
|
|
664
|
+
const base = BigInt(coin.amount);
|
|
665
|
+
const delta = (base * BigInt(slippageBps)) / BigInt(10_000);
|
|
666
|
+
const adjustedAmount = base + delta;
|
|
667
|
+
return Coin.fromPartial({ amount: adjustedAmount.toString(), denom: coin.denom });
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Checks if a fee range represents a fixed fee (minAmount equals maxAmount).
|
|
671
|
+
* @param feeRange - Fee range to check
|
|
672
|
+
* @returns True if the fee range is fixed, false otherwise
|
|
673
|
+
*/
|
|
674
|
+
static isFixedRange(feeRange) {
|
|
675
|
+
return feeRange.minAmount === feeRange.maxAmount;
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Validates a DID document against the Cheqd specification requirements.
|
|
679
|
+
* Ensures all required fields are present and verification methods are supported.
|
|
680
|
+
*
|
|
681
|
+
* @param didDocument - DID document to validate
|
|
682
|
+
* @returns Promise resolving to validation result with protobuf conversion or error details
|
|
683
|
+
*/
|
|
684
|
+
static async validateSpecCompliantPayload(didDocument) {
|
|
685
|
+
// id is required, validated on both compile and runtime
|
|
686
|
+
if (!didDocument?.id)
|
|
687
|
+
return { valid: false, error: 'id is required' };
|
|
688
|
+
// verificationMethod is required
|
|
689
|
+
if (!didDocument?.verificationMethod)
|
|
690
|
+
return { valid: false, error: 'verificationMethod is required' };
|
|
691
|
+
// verificationMethod must be an array
|
|
692
|
+
if (!Array.isArray(didDocument?.verificationMethod))
|
|
693
|
+
return { valid: false, error: 'verificationMethod must be an array' };
|
|
694
|
+
// verificationMethod types must be supported
|
|
695
|
+
const protoVerificationMethod = didDocument.verificationMethod.map((vm) => {
|
|
696
|
+
switch (vm?.type) {
|
|
697
|
+
case VerificationMethods.Ed255192020:
|
|
698
|
+
if (!vm?.publicKeyMultibase)
|
|
699
|
+
throw new Error('publicKeyMultibase is required');
|
|
700
|
+
return VerificationMethod.fromPartial({
|
|
701
|
+
id: vm.id,
|
|
702
|
+
controller: vm.controller,
|
|
703
|
+
verificationMethodType: VerificationMethods.Ed255192020,
|
|
704
|
+
verificationMaterial: vm.publicKeyMultibase,
|
|
705
|
+
});
|
|
706
|
+
case VerificationMethods.JWK:
|
|
707
|
+
if (!vm?.publicKeyJwk)
|
|
708
|
+
throw new Error('publicKeyJwk is required');
|
|
709
|
+
return VerificationMethod.fromPartial({
|
|
710
|
+
id: vm.id,
|
|
711
|
+
controller: vm.controller,
|
|
712
|
+
verificationMethodType: VerificationMethods.JWK,
|
|
713
|
+
verificationMaterial: JSON.stringify(vm.publicKeyJwk),
|
|
714
|
+
});
|
|
715
|
+
case VerificationMethods.Ed255192018:
|
|
716
|
+
if (!vm?.publicKeyBase58)
|
|
717
|
+
throw new Error('publicKeyBase58 is required');
|
|
718
|
+
return VerificationMethod.fromPartial({
|
|
719
|
+
id: vm.id,
|
|
720
|
+
controller: vm.controller,
|
|
721
|
+
verificationMethodType: VerificationMethods.Ed255192018,
|
|
722
|
+
verificationMaterial: vm.publicKeyBase58,
|
|
723
|
+
});
|
|
724
|
+
default:
|
|
725
|
+
throw new Error('Unsupported verificationMethod type');
|
|
726
|
+
}
|
|
727
|
+
});
|
|
728
|
+
const protoService = normalizeService(didDocument);
|
|
729
|
+
return {
|
|
730
|
+
valid: true,
|
|
731
|
+
protobufVerificationMethod: protoVerificationMethod,
|
|
732
|
+
protobufService: protoService,
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Converts a protobuf DID document to a specification-compliant DID document format.
|
|
737
|
+
* Handles context inclusion, verification method formatting, and service denormalization.
|
|
738
|
+
*
|
|
739
|
+
* @param protobufDidDocument - Protobuf DID document to convert
|
|
740
|
+
* @returns Promise resolving to a spec-compliant DID document
|
|
741
|
+
*/
|
|
742
|
+
static async toSpecCompliantPayload(protobufDidDocument) {
|
|
743
|
+
const verificationMethod = protobufDidDocument.verificationMethod.map((vm) => {
|
|
744
|
+
switch (vm.verificationMethodType) {
|
|
745
|
+
case VerificationMethods.Ed255192020:
|
|
746
|
+
if (!protobufDidDocument.context.includes(contexts.W3CSuiteEd255192020))
|
|
747
|
+
protobufDidDocument.context = [...protobufDidDocument.context, contexts.W3CSuiteEd255192020];
|
|
748
|
+
return {
|
|
749
|
+
id: vm.id,
|
|
750
|
+
type: vm.verificationMethodType,
|
|
751
|
+
controller: vm.controller,
|
|
752
|
+
publicKeyMultibase: vm.verificationMaterial,
|
|
753
|
+
};
|
|
754
|
+
case VerificationMethods.JWK:
|
|
755
|
+
if (!protobufDidDocument.context.includes(contexts.W3CSuiteJws2020))
|
|
756
|
+
protobufDidDocument.context = [...protobufDidDocument.context, contexts.W3CSuiteJws2020];
|
|
757
|
+
return {
|
|
758
|
+
id: vm.id,
|
|
759
|
+
type: vm.verificationMethodType,
|
|
760
|
+
controller: vm.controller,
|
|
761
|
+
publicKeyJwk: JSON.parse(vm.verificationMaterial),
|
|
762
|
+
};
|
|
763
|
+
case VerificationMethods.Ed255192018:
|
|
764
|
+
if (!protobufDidDocument.context.includes(contexts.W3CSuiteEd255192018))
|
|
765
|
+
protobufDidDocument.context = [...protobufDidDocument.context, contexts.W3CSuiteEd255192018];
|
|
766
|
+
return {
|
|
767
|
+
id: vm.id,
|
|
768
|
+
type: vm.verificationMethodType,
|
|
769
|
+
controller: vm.controller,
|
|
770
|
+
publicKeyBase58: vm.verificationMaterial,
|
|
771
|
+
};
|
|
772
|
+
default:
|
|
773
|
+
throw new Error('Unsupported verificationMethod type'); // should never happen
|
|
774
|
+
}
|
|
775
|
+
});
|
|
776
|
+
const service = denormalizeService(protobufDidDocument);
|
|
777
|
+
const context = (function () {
|
|
778
|
+
if (protobufDidDocument.context.includes(contexts.W3CDIDv1))
|
|
779
|
+
return protobufDidDocument.context;
|
|
780
|
+
return [contexts.W3CDIDv1, ...protobufDidDocument.context];
|
|
781
|
+
})();
|
|
782
|
+
const assertionMethod = protobufDidDocument.assertionMethod.map((am) => {
|
|
783
|
+
try {
|
|
784
|
+
// Check if the assertionMethod is a DID URL
|
|
785
|
+
if (!am.startsWith('did:cheqd:')) {
|
|
786
|
+
// Parse once if it's a stringified JSON
|
|
787
|
+
const parsedAm = JSON.parse(am);
|
|
788
|
+
if (typeof parsedAm === 'string') {
|
|
789
|
+
// Parse again only if necessary
|
|
790
|
+
return JSON.parse(parsedAm);
|
|
791
|
+
}
|
|
792
|
+
return parsedAm;
|
|
793
|
+
}
|
|
794
|
+
return am;
|
|
795
|
+
}
|
|
796
|
+
catch (error) {
|
|
797
|
+
throw new Error(`Unsupported assertionMethod type: ${am}`);
|
|
798
|
+
}
|
|
799
|
+
});
|
|
800
|
+
const specCompliant = {
|
|
801
|
+
'@context': context,
|
|
802
|
+
id: protobufDidDocument.id,
|
|
803
|
+
controller: protobufDidDocument.controller,
|
|
804
|
+
verificationMethod: verificationMethod,
|
|
805
|
+
authentication: protobufDidDocument.authentication,
|
|
806
|
+
assertionMethod: assertionMethod,
|
|
807
|
+
capabilityInvocation: protobufDidDocument.capabilityInvocation,
|
|
808
|
+
capabilityDelegation: protobufDidDocument.capabilityDelegation,
|
|
809
|
+
keyAgreement: protobufDidDocument.keyAgreement,
|
|
810
|
+
service: service,
|
|
811
|
+
alsoKnownAs: protobufDidDocument.alsoKnownAs,
|
|
812
|
+
};
|
|
813
|
+
if (!protobufDidDocument.authentication?.length)
|
|
814
|
+
delete specCompliant.authentication;
|
|
815
|
+
if (!protobufDidDocument.assertionMethod?.length)
|
|
816
|
+
delete specCompliant.assertionMethod;
|
|
817
|
+
if (!protobufDidDocument.capabilityInvocation?.length)
|
|
818
|
+
delete specCompliant.capabilityInvocation;
|
|
819
|
+
if (!protobufDidDocument.capabilityDelegation?.length)
|
|
820
|
+
delete specCompliant.capabilityDelegation;
|
|
821
|
+
if (!protobufDidDocument.keyAgreement?.length)
|
|
822
|
+
delete specCompliant.keyAgreement;
|
|
823
|
+
if (!protobufDidDocument.service?.length)
|
|
824
|
+
delete specCompliant.service;
|
|
825
|
+
if (!protobufDidDocument.alsoKnownAs?.length)
|
|
826
|
+
delete specCompliant.alsoKnownAs;
|
|
827
|
+
return specCompliant;
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Converts protobuf metadata to specification-compliant DID document metadata format.
|
|
831
|
+
* Handles date formatting and optional field normalization.
|
|
832
|
+
*
|
|
833
|
+
* @param protobufDidDocument - Protobuf metadata to convert
|
|
834
|
+
* @returns Promise resolving to spec-compliant DID document metadata
|
|
835
|
+
*/
|
|
836
|
+
static async toSpecCompliantMetadata(protobufDidDocument) {
|
|
837
|
+
return {
|
|
838
|
+
created: protobufDidDocument.created?.toISOString(),
|
|
839
|
+
updated: protobufDidDocument.updated?.toISOString(),
|
|
840
|
+
deactivated: protobufDidDocument.deactivated,
|
|
841
|
+
versionId: protobufDidDocument.versionId,
|
|
842
|
+
nextVersionId: protobufDidDocument?.nextVersionId,
|
|
843
|
+
previousVersionId: protobufDidDocument?.previousVersionId,
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* Validates that provided signatures match the authentication requirements in a DID document.
|
|
848
|
+
* Checks signature count, authentication presence, and controller authorization.
|
|
849
|
+
*
|
|
850
|
+
* @param didDocument - DID document containing authentication requirements
|
|
851
|
+
* @param signatures - Array of signatures to validate against authentication
|
|
852
|
+
* @param querier - Optional querier for retrieving external controller documents
|
|
853
|
+
* @param externalControllersDidDocuments - Optional pre-loaded external controller documents
|
|
854
|
+
* @returns Promise resolving to validation result with error details if invalid
|
|
855
|
+
*/
|
|
856
|
+
static async validateAuthenticationAgainstSignatures(didDocument, signatures, querier, externalControllersDidDocuments) {
|
|
857
|
+
// validate signatures - case: no signatures
|
|
858
|
+
if (!signatures || !signatures.length)
|
|
859
|
+
return { valid: false, error: 'signatures are required' };
|
|
860
|
+
// validate authentication - case: no authentication when at least one verificationMethod
|
|
861
|
+
if ((!didDocument.authentication || !didDocument.authentication.length) &&
|
|
862
|
+
didDocument.verificationMethod?.length)
|
|
863
|
+
return { valid: false, error: 'authentication is required' };
|
|
864
|
+
const normalizedAuthentication = normalizeAuthentication(didDocument);
|
|
865
|
+
// define unique authentication
|
|
866
|
+
const uniqueAuthentication = new Set(normalizedAuthentication);
|
|
867
|
+
// validate authentication - case: authentication contains duplicates
|
|
868
|
+
if (uniqueAuthentication.size < normalizedAuthentication.length)
|
|
869
|
+
return {
|
|
870
|
+
valid: false,
|
|
871
|
+
error: `authentication contains duplicate key references: duplicate key reference ${Array.from(uniqueAuthentication).find((a) => normalizeAuthentication(didDocument).filter((aa) => aa === a).length > 1)}`,
|
|
872
|
+
};
|
|
873
|
+
// define unique signatures - shallow, only verificationMethodId, no signature
|
|
874
|
+
const uniqueSignatures = new Set(signatures.map((s) => s.verificationMethodId));
|
|
875
|
+
// validate signatures - case: signatures contain duplicates
|
|
876
|
+
if (uniqueSignatures.size < signatures.length)
|
|
877
|
+
return {
|
|
878
|
+
valid: false,
|
|
879
|
+
error: `signatures contain duplicates: duplicate signature for key reference ${Array.from(uniqueSignatures).find((s) => signatures.filter((ss) => ss.verificationMethodId === s).length > 1)}`,
|
|
880
|
+
};
|
|
881
|
+
// validate authentication - case: authentication contains invalid key references
|
|
882
|
+
if (!Array.from(uniqueAuthentication).every((a) => didDocument.verificationMethod?.some((vm) => vm.id === a)))
|
|
883
|
+
return {
|
|
884
|
+
valid: false,
|
|
885
|
+
error: `authentication contains invalid key references: invalid key reference ${Array.from(uniqueAuthentication).find((a) => !didDocument.verificationMethod?.some((vm) => vm.id === a))}`,
|
|
886
|
+
};
|
|
887
|
+
// define whether external controller or not
|
|
888
|
+
const externalController = normalizeController(didDocument).some((c) => c !== didDocument.id);
|
|
889
|
+
// validate authentication - case: authentication matches signatures, unique, if no external controller
|
|
890
|
+
if (!Array.from(uniqueAuthentication).every((a) => uniqueSignatures.has(a)) && !externalController)
|
|
891
|
+
return {
|
|
892
|
+
valid: false,
|
|
893
|
+
error: `authentication does not match signatures: signature from key ${Array.from(uniqueAuthentication).find((a) => !uniqueSignatures.has(a))} is missing`,
|
|
894
|
+
};
|
|
895
|
+
// validate signatures - case: authentication matches signatures, unique, excessive signatures, no external controller
|
|
896
|
+
if (!Array.from(uniqueSignatures).every((s) => uniqueAuthentication.has(s)) && !externalController)
|
|
897
|
+
return {
|
|
898
|
+
valid: false,
|
|
899
|
+
error: `authentication does not match signatures: signature from key ${Array.from(uniqueSignatures).find((s) => !uniqueAuthentication.has(s))} is not required`,
|
|
900
|
+
};
|
|
901
|
+
// return, if no external controller
|
|
902
|
+
if (!externalController)
|
|
903
|
+
return { valid: true };
|
|
904
|
+
// require querier
|
|
905
|
+
if (!querier)
|
|
906
|
+
throw new Error('querier is required for external controller validation');
|
|
907
|
+
// get external controllers
|
|
908
|
+
const externalControllers = normalizeController(didDocument).filter((c) => c !== didDocument.id);
|
|
909
|
+
// get external controllers' documents
|
|
910
|
+
const externalControllersDocuments = await Promise.all(externalControllers?.map(async (c) => {
|
|
911
|
+
// compute index of external controller's document, if provided
|
|
912
|
+
const externalControllerDocumentIndex = externalControllersDidDocuments?.findIndex((d) => d.id === c);
|
|
913
|
+
// get external controller's document, if provided
|
|
914
|
+
if (externalControllerDocumentIndex !== undefined && externalControllerDocumentIndex !== -1)
|
|
915
|
+
return externalControllersDidDocuments?.[externalControllerDocumentIndex];
|
|
916
|
+
// fetch external controller's document
|
|
917
|
+
const protobufDocument = await querier[defaultDidExtensionKey].didDoc(c);
|
|
918
|
+
// throw, if not found
|
|
919
|
+
if (!protobufDocument || !protobufDocument.didDoc)
|
|
920
|
+
throw new Error(`Document for controller ${c} not found`);
|
|
921
|
+
// convert to spec compliant payload
|
|
922
|
+
return await DIDModule.toSpecCompliantPayload(protobufDocument.didDoc);
|
|
923
|
+
}));
|
|
924
|
+
// define unique required signatures
|
|
925
|
+
const uniqueRequiredSignatures = new Set(externalControllersDocuments.concat(didDocument).flatMap((d) => (d ? normalizeAuthentication(d) : [])));
|
|
926
|
+
// validate authentication - case: authentication matches signatures, unique, if external controller
|
|
927
|
+
if (!Array.from(uniqueRequiredSignatures).every((a) => uniqueSignatures.has(a)))
|
|
928
|
+
return {
|
|
929
|
+
valid: false,
|
|
930
|
+
error: `authentication does not match signatures: signature from key ${Array.from(uniqueRequiredSignatures).find((a) => !uniqueSignatures.has(a))} is missing`,
|
|
931
|
+
};
|
|
932
|
+
// validate authentication - case: authentication matches signatures, unique, excessive signatures, if external controller
|
|
933
|
+
if (uniqueRequiredSignatures.size < uniqueSignatures.size)
|
|
934
|
+
return {
|
|
935
|
+
valid: false,
|
|
936
|
+
error: `authentication does not match signatures: signature from key ${Array.from(uniqueSignatures).find((s) => !uniqueRequiredSignatures.has(s))} is not required`,
|
|
937
|
+
};
|
|
938
|
+
// return valid
|
|
939
|
+
return { valid: true };
|
|
940
|
+
}
|
|
941
|
+
/**
|
|
942
|
+
* Validates authentication against signatures for key rotation scenarios.
|
|
943
|
+
* Handles validation during DID document updates where keys may have changed.
|
|
944
|
+
*
|
|
945
|
+
* @param didDocument - Updated DID document to validate
|
|
946
|
+
* @param signatures - Array of signatures to validate
|
|
947
|
+
* @param querier - Querier for retrieving previous DID document and controllers
|
|
948
|
+
* @param previousDidDocument - Optional previous version of the DID document
|
|
949
|
+
* @param externalControllersDidDocuments - Optional pre-loaded external controller documents
|
|
950
|
+
* @returns Promise resolving to validation result with controller documents and previous document
|
|
951
|
+
*/
|
|
952
|
+
static async validateAuthenticationAgainstSignaturesKeyRotation(didDocument, signatures, querier, previousDidDocument, externalControllersDidDocuments) {
|
|
953
|
+
// validate signatures - case: no signatures
|
|
954
|
+
if (!signatures || !signatures.length)
|
|
955
|
+
return { valid: false, error: 'signatures are required' };
|
|
956
|
+
// validate authentication - case: no authentication when at least one verificationMethod
|
|
957
|
+
if ((!didDocument.authentication || !didDocument.authentication.length) &&
|
|
958
|
+
didDocument.verificationMethod?.length)
|
|
959
|
+
return { valid: false, error: 'authentication is required' };
|
|
960
|
+
// define unique authentication
|
|
961
|
+
const authentication = normalizeAuthentication(didDocument);
|
|
962
|
+
const uniqueAuthentication = new Set(authentication);
|
|
963
|
+
// validate authentication - case: authentication contains duplicates
|
|
964
|
+
if (uniqueAuthentication.size < authentication.length)
|
|
965
|
+
return {
|
|
966
|
+
valid: false,
|
|
967
|
+
error: `authentication contains duplicate key references: duplicate key reference ${Array.from(uniqueAuthentication).find((a) => normalizeAuthentication(didDocument).filter((aa) => aa === a).length > 1)}`,
|
|
968
|
+
};
|
|
969
|
+
// define unique signatures
|
|
970
|
+
const uniqueSignatures = new Set(signatures.map((s) => s.verificationMethodId));
|
|
971
|
+
// validate authentication - case: authentication contains invalid key references
|
|
972
|
+
if (!Array.from(uniqueAuthentication).every((a) => didDocument.verificationMethod?.some((vm) => vm.id === a)))
|
|
973
|
+
return {
|
|
974
|
+
valid: false,
|
|
975
|
+
error: `authentication contains invalid key references: invalid key reference ${Array.from(uniqueAuthentication).find((a) => !didDocument.verificationMethod?.some((vm) => vm.id === a))}`,
|
|
976
|
+
};
|
|
977
|
+
// lookup previous document
|
|
978
|
+
if (!previousDidDocument) {
|
|
979
|
+
// get previous document
|
|
980
|
+
const previousDocument = await querier[defaultDidExtensionKey].didDoc(didDocument.id);
|
|
981
|
+
// throw, if not found
|
|
982
|
+
if (!previousDocument || !previousDocument.didDoc)
|
|
983
|
+
throw new Error('Previous did document not found');
|
|
984
|
+
previousDidDocument = await DIDModule.toSpecCompliantPayload(previousDocument.didDoc);
|
|
985
|
+
}
|
|
986
|
+
const controllers = normalizeController(didDocument);
|
|
987
|
+
const previousControllers = normalizeController(previousDidDocument);
|
|
988
|
+
// define whether external controller or not
|
|
989
|
+
const externalController = controllers.concat(previousControllers).some((c) => c !== didDocument.id);
|
|
990
|
+
// define whether key rotation or not (same ID, different material)
|
|
991
|
+
const keyRotation = !!didDocument.verificationMethod?.some((vm) => previousDidDocument?.verificationMethod?.some((pvm) => pvm.id === vm.id &&
|
|
992
|
+
(pvm.publicKeyBase58 !== vm.publicKeyBase58 ||
|
|
993
|
+
pvm.publicKeyMultibase !== vm.publicKeyMultibase ||
|
|
994
|
+
pvm.publicKeyJwk?.x !== vm.publicKeyJwk?.x)));
|
|
995
|
+
// define whether key replacement or not (different IDs in authentication)
|
|
996
|
+
const currentAuthenticationIds = new Set(normalizeAuthentication(didDocument));
|
|
997
|
+
const previousAuthenticationIds = new Set(normalizeAuthentication(previousDidDocument));
|
|
998
|
+
const removedKeys = Array.from(previousAuthenticationIds).filter((id) => !currentAuthenticationIds.has(id));
|
|
999
|
+
const addedKeys = Array.from(currentAuthenticationIds).filter((id) => !previousAuthenticationIds.has(id));
|
|
1000
|
+
const keyReplacement = removedKeys.length > 0 && addedKeys.length > 0;
|
|
1001
|
+
// define controller rotation
|
|
1002
|
+
const controllerRotation = !controllers.every((c) => previousControllers.includes(c)) ||
|
|
1003
|
+
!previousControllers.every((c) => controllers.includes(c));
|
|
1004
|
+
// define rotated controllers
|
|
1005
|
+
const rotatedControllers = controllerRotation
|
|
1006
|
+
? previousControllers.filter((c) => !controllers.includes(c))
|
|
1007
|
+
: [];
|
|
1008
|
+
// define unique union of authentication
|
|
1009
|
+
const previousAuthentication = normalizeAuthentication(previousDidDocument);
|
|
1010
|
+
const uniqueUnionAuthentication = new Set([...uniqueAuthentication, ...previousAuthentication]);
|
|
1011
|
+
// validate authentication - case: authentication matches signatures, unique, if no external controller, no key rotation, no key replacement
|
|
1012
|
+
if (!Array.from(uniqueUnionAuthentication).every((a) => uniqueSignatures.has(a)) &&
|
|
1013
|
+
!externalController &&
|
|
1014
|
+
!keyRotation &&
|
|
1015
|
+
!keyReplacement)
|
|
1016
|
+
return {
|
|
1017
|
+
valid: false,
|
|
1018
|
+
error: `authentication does not match signatures: signature from key ${Array.from(uniqueAuthentication).find((a) => !uniqueSignatures.has(a))} is missing`,
|
|
1019
|
+
};
|
|
1020
|
+
// define rotated keys
|
|
1021
|
+
const rotatedKeys = keyRotation
|
|
1022
|
+
? didDocument.verificationMethod?.filter((vm) => previousDidDocument?.verificationMethod?.some((pvm) => pvm.id === vm.id &&
|
|
1023
|
+
(pvm.publicKeyBase58 !== vm.publicKeyBase58 ||
|
|
1024
|
+
pvm.publicKeyMultibase !== vm.publicKeyMultibase ||
|
|
1025
|
+
pvm.publicKeyJwk?.x !== vm.publicKeyJwk?.x)))
|
|
1026
|
+
: [];
|
|
1027
|
+
// define unique union of signatures required, including key replacement logic
|
|
1028
|
+
let uniqueUnionSignaturesRequired = new Set();
|
|
1029
|
+
if (keyRotation && keyReplacement) {
|
|
1030
|
+
// Combined operation: Both key rotation AND key replacement happening
|
|
1031
|
+
// Need signatures from:
|
|
1032
|
+
// 1. All rotated keys (both old and new material for same ID)
|
|
1033
|
+
// 2. All added keys (new keys being added)
|
|
1034
|
+
// 3. All removed keys (old keys being removed)
|
|
1035
|
+
const rotatedKeySignatures = authentication
|
|
1036
|
+
.filter((a) => rotatedKeys?.find((rk) => a === rk.id))
|
|
1037
|
+
.map((a) => `${a}(document0)`);
|
|
1038
|
+
const previousRotatedKeySignatures = previousAuthentication
|
|
1039
|
+
.filter((a) => rotatedKeys?.find((rk) => a === rk.id))
|
|
1040
|
+
.map((a) => `${a}(document1)`);
|
|
1041
|
+
const newKeySignatures = addedKeys
|
|
1042
|
+
.filter((keyId) => !rotatedKeys?.find((rk) => keyId === rk.id))
|
|
1043
|
+
.map((keyId) => `${keyId}(document0)`);
|
|
1044
|
+
const oldKeySignatures = removedKeys
|
|
1045
|
+
.filter((keyId) => previousAuthentication.includes(keyId))
|
|
1046
|
+
.map((keyId) => `${keyId}(document1)`);
|
|
1047
|
+
uniqueUnionSignaturesRequired = new Set([
|
|
1048
|
+
...rotatedKeySignatures,
|
|
1049
|
+
...previousRotatedKeySignatures,
|
|
1050
|
+
...newKeySignatures,
|
|
1051
|
+
...oldKeySignatures,
|
|
1052
|
+
]);
|
|
1053
|
+
}
|
|
1054
|
+
else if (keyRotation) {
|
|
1055
|
+
// Key rotation only (same ID, different material)
|
|
1056
|
+
uniqueUnionSignaturesRequired = new Set([
|
|
1057
|
+
...authentication.filter((a) => rotatedKeys?.find((rk) => a === rk.id)).map((a) => `${a}(document0)`),
|
|
1058
|
+
...previousAuthentication.map((a) => `${a}(document1)`),
|
|
1059
|
+
]);
|
|
1060
|
+
}
|
|
1061
|
+
else if (keyReplacement) {
|
|
1062
|
+
// Key replacement only (different IDs in authentication)
|
|
1063
|
+
// For key replacement, we need signatures from:
|
|
1064
|
+
// 1. The new keys (from current document)
|
|
1065
|
+
// 2. The old keys that are being replaced (from previous document)
|
|
1066
|
+
const newKeySignatures = addedKeys.map((keyId) => `${keyId}(document0)`);
|
|
1067
|
+
const oldKeySignatures = removedKeys
|
|
1068
|
+
.filter((keyId) => previousAuthentication.includes(keyId)) // Only if they were in authentication
|
|
1069
|
+
.map((keyId) => `${keyId}(document1)`);
|
|
1070
|
+
uniqueUnionSignaturesRequired = new Set([...newKeySignatures, ...oldKeySignatures]);
|
|
1071
|
+
}
|
|
1072
|
+
else {
|
|
1073
|
+
const oldKeySignatures = removedKeys
|
|
1074
|
+
.filter((keyId) => previousAuthentication.includes(keyId)) // Only if they were in authentication
|
|
1075
|
+
.map((keyId) => `${keyId}(document1)`);
|
|
1076
|
+
// current authentication and any removed authentication key signatures
|
|
1077
|
+
uniqueUnionSignaturesRequired = new Set([
|
|
1078
|
+
...authentication.map((a) => `${a}(document0)`),
|
|
1079
|
+
...oldKeySignatures,
|
|
1080
|
+
]);
|
|
1081
|
+
}
|
|
1082
|
+
// define frequency of unique union of signatures required
|
|
1083
|
+
const uniqueUnionSignaturesRequiredFrequency = new Map([...uniqueUnionSignaturesRequired].map((s) => [s.replace(new RegExp(/\(document\d+\)/), ''), 0]));
|
|
1084
|
+
// count frequency of unique union of signatures required
|
|
1085
|
+
uniqueUnionSignaturesRequired.forEach((s) => {
|
|
1086
|
+
// define key
|
|
1087
|
+
const key = s.replace(new RegExp(/\(document\d+\)/), '');
|
|
1088
|
+
// increment frequency
|
|
1089
|
+
uniqueUnionSignaturesRequiredFrequency.set(key, uniqueUnionSignaturesRequiredFrequency.get(key) + 1);
|
|
1090
|
+
});
|
|
1091
|
+
// define frequency of signatures provided
|
|
1092
|
+
const uniqueSignaturesFrequency = new Map(signatures.map((s) => [s.verificationMethodId, 0]));
|
|
1093
|
+
// count frequency of signatures provided
|
|
1094
|
+
signatures.forEach((s) => {
|
|
1095
|
+
// increment frequency
|
|
1096
|
+
uniqueSignaturesFrequency.set(s.verificationMethodId, uniqueSignaturesFrequency.get(s.verificationMethodId) + 1);
|
|
1097
|
+
});
|
|
1098
|
+
// validate signatures - case: authentication matches signatures, unique, excessive signatures, no external controller
|
|
1099
|
+
if (Array.from(uniqueSignaturesFrequency).filter(([k, f]) => uniqueUnionSignaturesRequiredFrequency.get(k) === undefined ||
|
|
1100
|
+
(uniqueUnionSignaturesRequiredFrequency.get(k) &&
|
|
1101
|
+
uniqueUnionSignaturesRequiredFrequency.get(k) < f)).length &&
|
|
1102
|
+
!externalController)
|
|
1103
|
+
return {
|
|
1104
|
+
valid: false,
|
|
1105
|
+
error: `authentication does not match signatures: signature from key ${Array.from(uniqueSignaturesFrequency).find(([k, f]) => uniqueUnionSignaturesRequiredFrequency.get(k) === undefined || uniqueUnionSignaturesRequiredFrequency.get(k) < f)?.[0]} is not required`,
|
|
1106
|
+
};
|
|
1107
|
+
// validate signatures - case: authentication matches signatures, unique, missing signatures, no external controller
|
|
1108
|
+
if (Array.from(uniqueSignaturesFrequency).filter(([k, f]) => uniqueUnionSignaturesRequiredFrequency.get(k) && uniqueUnionSignaturesRequiredFrequency.get(k) > f).length &&
|
|
1109
|
+
!externalController)
|
|
1110
|
+
return {
|
|
1111
|
+
valid: false,
|
|
1112
|
+
error: `authentication does not match signatures: signature from key ${Array.from(uniqueSignaturesFrequency).find(([k, f]) => uniqueUnionSignaturesRequiredFrequency.get(k) > f)?.[0]} is missing`,
|
|
1113
|
+
};
|
|
1114
|
+
// validate signatures - case: all required keys must have signatures provided (check for completely missing keys)
|
|
1115
|
+
if (!externalController) {
|
|
1116
|
+
const missingKeys = Array.from(uniqueUnionSignaturesRequiredFrequency.keys()).filter((requiredKey) => !uniqueSignaturesFrequency.has(requiredKey));
|
|
1117
|
+
if (missingKeys.length > 0) {
|
|
1118
|
+
return {
|
|
1119
|
+
valid: false,
|
|
1120
|
+
error: `authentication does not match signatures: signature from key ${missingKeys[0]} is missing`,
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
// require querier
|
|
1125
|
+
if (!querier)
|
|
1126
|
+
throw new Error('querier is required for external controller validation');
|
|
1127
|
+
// get external controllers
|
|
1128
|
+
// Only include rotated controllers if they are external (not the current DID itself)
|
|
1129
|
+
const externalRotatedControllers = rotatedControllers.filter((c) => c !== didDocument.id);
|
|
1130
|
+
const externalControllers = controllers?.filter((c) => c !== didDocument.id).concat(externalRotatedControllers);
|
|
1131
|
+
// get external controllers' documents
|
|
1132
|
+
const externalControllersDocuments = await Promise.all(externalControllers?.map(async (c) => {
|
|
1133
|
+
// compute index of external controller's document, if provided
|
|
1134
|
+
const externalControllerDocumentIndex = externalControllersDidDocuments?.findIndex((d) => d.id === c);
|
|
1135
|
+
// get external controller's document, if provided
|
|
1136
|
+
if (externalControllerDocumentIndex !== undefined && externalControllerDocumentIndex !== -1)
|
|
1137
|
+
return externalControllersDidDocuments[externalControllerDocumentIndex];
|
|
1138
|
+
// fetch external controller's document
|
|
1139
|
+
const protobufDocument = await querier[defaultDidExtensionKey].didDoc(c);
|
|
1140
|
+
// throw, if not found
|
|
1141
|
+
if (!protobufDocument || !protobufDocument.didDoc)
|
|
1142
|
+
throw new Error(`Document for controller ${c} not found`);
|
|
1143
|
+
// convert to spec compliant payload
|
|
1144
|
+
return await DIDModule.toSpecCompliantPayload(protobufDocument.didDoc);
|
|
1145
|
+
}));
|
|
1146
|
+
// define unique required signatures, delimited, with external controllers
|
|
1147
|
+
const uniqueUnionSignaturesRequiredWithExternalControllers = new Set([
|
|
1148
|
+
...uniqueUnionSignaturesRequired,
|
|
1149
|
+
...externalControllersDocuments
|
|
1150
|
+
.flatMap((d) => normalizeAuthentication(d))
|
|
1151
|
+
.map((a) => `${a}(document${externalControllersDocuments.findIndex((d) => normalizeAuthentication(d).includes(a))})`),
|
|
1152
|
+
]);
|
|
1153
|
+
// add rotated controller keys to unique required signatures, if any
|
|
1154
|
+
if (controllerRotation) {
|
|
1155
|
+
// walk through rotated controllers
|
|
1156
|
+
rotatedControllers.forEach((c) => {
|
|
1157
|
+
// get rotated controller's document index
|
|
1158
|
+
const rotatedControllerDocumentIndex = externalControllersDocuments.findIndex((d) => d?.id === c);
|
|
1159
|
+
// early return, if no document
|
|
1160
|
+
if (rotatedControllerDocumentIndex === -1)
|
|
1161
|
+
return;
|
|
1162
|
+
// get rotated controller's document
|
|
1163
|
+
const rotatedControllerDocument = externalControllersDocuments[rotatedControllerDocumentIndex];
|
|
1164
|
+
// add rotated controller's authentication to unique required signatures
|
|
1165
|
+
rotatedControllerDocument.authentication?.forEach((a) => uniqueUnionSignaturesRequiredWithExternalControllers.add(`${a}(document${rotatedControllerDocumentIndex})`));
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
1168
|
+
// define frequency of unique union of signatures required, with external controllers
|
|
1169
|
+
const uniqueUnionSignaturesRequiredWithExternalControllersFrequency = new Map([...uniqueUnionSignaturesRequiredWithExternalControllers].map((s) => [
|
|
1170
|
+
s.replace(new RegExp(/\(document\d+\)/), ''),
|
|
1171
|
+
0,
|
|
1172
|
+
]));
|
|
1173
|
+
// count frequency of unique union of signatures required, with external controllers
|
|
1174
|
+
uniqueUnionSignaturesRequiredWithExternalControllers.forEach((s) => {
|
|
1175
|
+
// define key
|
|
1176
|
+
const key = s.replace(new RegExp(/\(document\d+\)/), '');
|
|
1177
|
+
// increment frequency
|
|
1178
|
+
uniqueUnionSignaturesRequiredWithExternalControllersFrequency.set(key, uniqueUnionSignaturesRequiredWithExternalControllersFrequency.get(key) + 1);
|
|
1179
|
+
});
|
|
1180
|
+
// define frequency of signatures provided, with external controllers
|
|
1181
|
+
const uniqueSignaturesFrequencyWithExternalControllers = new Map(signatures.map((s) => [s.verificationMethodId, 0]));
|
|
1182
|
+
// count frequency of signatures provided, with external controllers
|
|
1183
|
+
signatures.forEach((s) => {
|
|
1184
|
+
// increment frequency
|
|
1185
|
+
uniqueSignaturesFrequencyWithExternalControllers.set(s.verificationMethodId, uniqueSignaturesFrequencyWithExternalControllers.get(s.verificationMethodId) + 1);
|
|
1186
|
+
});
|
|
1187
|
+
// validate signatures - case: authentication matches signatures, unique, excessive signatures, with external controllers
|
|
1188
|
+
if (Array.from(uniqueSignaturesFrequencyWithExternalControllers).filter(([k, f]) => uniqueUnionSignaturesRequiredWithExternalControllersFrequency.get(k) === undefined ||
|
|
1189
|
+
(uniqueUnionSignaturesRequiredWithExternalControllersFrequency.get(k) &&
|
|
1190
|
+
uniqueUnionSignaturesRequiredWithExternalControllersFrequency.get(k) < f)).length &&
|
|
1191
|
+
externalController)
|
|
1192
|
+
return {
|
|
1193
|
+
valid: false,
|
|
1194
|
+
error: `authentication does not match signatures: signature from key ${Array.from(uniqueSignaturesFrequencyWithExternalControllers).find(([k, f]) => uniqueUnionSignaturesRequiredWithExternalControllersFrequency.get(k) === undefined || uniqueUnionSignaturesRequiredWithExternalControllersFrequency.get(k) < f)?.[0]} is not required`,
|
|
1195
|
+
};
|
|
1196
|
+
// validate signatures - case: authentication matches signatures, unique, missing signatures, with external controllers
|
|
1197
|
+
if (Array.from(uniqueSignaturesFrequencyWithExternalControllers).filter(([k, f]) => uniqueUnionSignaturesRequiredWithExternalControllersFrequency.get(k) &&
|
|
1198
|
+
uniqueUnionSignaturesRequiredWithExternalControllersFrequency.get(k) > f).length &&
|
|
1199
|
+
externalController)
|
|
1200
|
+
return {
|
|
1201
|
+
valid: false,
|
|
1202
|
+
error: `authentication does not match signatures: signature from key ${Array.from(uniqueSignaturesFrequencyWithExternalControllers).find(([k, f]) => uniqueUnionSignaturesRequiredWithExternalControllersFrequency.get(k) > f)?.[0]} is missing`,
|
|
1203
|
+
};
|
|
1204
|
+
// return valid
|
|
1205
|
+
return { valid: true, previousDidDocument, externalControllersDocuments };
|
|
1206
|
+
}
|
|
1207
|
+
/**
|
|
1208
|
+
* Generates standard fees for creating a DID document.
|
|
1209
|
+
*
|
|
1210
|
+
* @param feePayer - Address of the account that will pay the transaction fees
|
|
1211
|
+
* @param granter - Optional address of the account granting fee payment permissions
|
|
1212
|
+
* @returns Promise resolving to the fee configuration for DID document creation
|
|
1213
|
+
*/
|
|
1214
|
+
static async generateCreateDidDocFees(feePayer, granter) {
|
|
1215
|
+
return {
|
|
1216
|
+
amount: [DIDModule.fees.DefaultCreateDidDocFee],
|
|
1217
|
+
gas: '360000',
|
|
1218
|
+
payer: feePayer,
|
|
1219
|
+
granter: granter,
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Generates fee configuration for DID document update transactions.
|
|
1224
|
+
* Uses default update fees and gas requirements.
|
|
1225
|
+
*
|
|
1226
|
+
* @param feePayer - Address of the account that will pay the transaction fees
|
|
1227
|
+
* @param granter - Optional address of the account granting fee payment permissions
|
|
1228
|
+
* @returns Promise resolving to the fee configuration for DID document updates
|
|
1229
|
+
*/
|
|
1230
|
+
static async generateUpdateDidDocFees(feePayer, granter) {
|
|
1231
|
+
return {
|
|
1232
|
+
amount: [DIDModule.fees.DefaultUpdateDidDocFee],
|
|
1233
|
+
gas: '360000',
|
|
1234
|
+
payer: feePayer,
|
|
1235
|
+
granter: granter,
|
|
1236
|
+
};
|
|
1237
|
+
}
|
|
1238
|
+
/**
|
|
1239
|
+
* Generates fee configuration for DID document deactivation transactions.
|
|
1240
|
+
* Uses default deactivation fees and gas requirements.
|
|
1241
|
+
*
|
|
1242
|
+
* @param feePayer - Address of the account that will pay the transaction fees
|
|
1243
|
+
* @param granter - Optional address of the account granting fee payment permissions
|
|
1244
|
+
* @returns Promise resolving to the fee configuration for DID document deactivation
|
|
1245
|
+
*/
|
|
1246
|
+
static async generateDeactivateDidDocFees(feePayer, granter) {
|
|
1247
|
+
return {
|
|
1248
|
+
amount: [DIDModule.fees.DefaultDeactivateDidDocFee],
|
|
1249
|
+
gas: '360000',
|
|
1250
|
+
payer: feePayer,
|
|
1251
|
+
granter: granter,
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
//# sourceMappingURL=did.js.map
|