@0xpolygonid/js-sdk 1.6.1 → 1.7.0

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.
Files changed (33) hide show
  1. package/README.md +3 -1
  2. package/dist/browser/esm/index.js +738 -491
  3. package/dist/browser/esm/index.js.map +1 -1
  4. package/dist/browser/umd/index.js +784 -531
  5. package/dist/browser/umd/index.js.map +1 -1
  6. package/dist/node/cjs/circuits/comparer.js +3 -3
  7. package/dist/node/cjs/credentials/credential-wallet.js +19 -2
  8. package/dist/node/cjs/credentials/index.js +1 -0
  9. package/dist/node/cjs/credentials/rhs.js +28 -15
  10. package/dist/node/cjs/credentials/status/credential-status-publisher.js +84 -0
  11. package/dist/node/cjs/credentials/utils.js +14 -1
  12. package/dist/node/cjs/identity/identity-wallet.js +57 -26
  13. package/dist/node/cjs/storage/blockchain/abi/CredentialStatusResolver.json +1 -1
  14. package/dist/node/cjs/storage/blockchain/index.js +1 -0
  15. package/dist/node/cjs/storage/blockchain/onchain-revocation.js +45 -5
  16. package/dist/node/esm/circuits/comparer.js +3 -3
  17. package/dist/node/esm/credentials/credential-wallet.js +20 -3
  18. package/dist/node/esm/credentials/index.js +1 -0
  19. package/dist/node/esm/credentials/rhs.js +26 -14
  20. package/dist/node/esm/credentials/status/credential-status-publisher.js +78 -0
  21. package/dist/node/esm/credentials/utils.js +12 -0
  22. package/dist/node/esm/identity/identity-wallet.js +52 -21
  23. package/dist/node/esm/storage/blockchain/abi/CredentialStatusResolver.json +1 -1
  24. package/dist/node/esm/storage/blockchain/index.js +1 -0
  25. package/dist/node/esm/storage/blockchain/onchain-revocation.js +45 -5
  26. package/dist/types/credentials/index.d.ts +1 -0
  27. package/dist/types/credentials/rhs.d.ts +11 -0
  28. package/dist/types/credentials/status/credential-status-publisher.d.ts +70 -0
  29. package/dist/types/credentials/utils.d.ts +2 -0
  30. package/dist/types/identity/identity-wallet.d.ts +42 -13
  31. package/dist/types/storage/blockchain/index.d.ts +1 -0
  32. package/dist/types/storage/blockchain/onchain-revocation.d.ts +7 -3
  33. package/package.json +1 -1
@@ -1,13 +1,16 @@
1
- import { newHashFromBigInt, testBit, NodeLeaf } from '@iden3/js-merkletree';
1
+ import { Hash, testBit, NodeLeaf } from '@iden3/js-merkletree';
2
2
  import { NODE_TYPE_LEAF } from '@iden3/js-merkletree';
3
3
  import { hashElems } from '@iden3/js-merkletree';
4
4
  import { ProofNode } from './status/reverse-sparse-merkle-tree';
5
+ import { Iden3SmtRhsCredentialStatusPublisher } from './status/credential-status-publisher';
6
+ import { CredentialStatusType } from '../verifiable';
5
7
  /**
6
8
  * Pushes identity state information to a reverse hash service.
7
9
  *
8
10
  * A reverse hash service (RHS) is a centralized or decentralized service for storing publicly available data about identity.
9
11
  * Such data are identity state and state of revocation tree and roots tree root tree.
10
12
  *
13
+ * @deprecated Use `pushHashesToReverseHashService` instead.
11
14
  * @param {Hash} state - current state of identity
12
15
  * @param {TreesModel} trees - current trees of identity (claims, revocation, rootOfRoots )
13
16
  * @param {string} rhsUrl - URL of service
@@ -15,6 +18,23 @@ import { ProofNode } from './status/reverse-sparse-merkle-tree';
15
18
  * @returns void
16
19
  */
17
20
  export async function pushHashesToRHS(state, trees, rhsUrl, revokedNonces) {
21
+ const nodes = await getNodesRepresentation(revokedNonces, trees, state);
22
+ const publisher = new Iden3SmtRhsCredentialStatusPublisher();
23
+ await publisher.publish({
24
+ nodes,
25
+ credentialStatusType: CredentialStatusType.Iden3ReverseSparseMerkleTreeProof,
26
+ rhsUrl: rhsUrl
27
+ });
28
+ }
29
+ /**
30
+ * Retrieves the representation of nodes for generating a proof.
31
+ *
32
+ * @param revokedNonces - An array of revoked nonces.
33
+ * @param trees - The TreesModel object containing the necessary trees.
34
+ * @param state - The hash of the state.
35
+ * @returns A Promise that resolves to an array of ProofNode objects.
36
+ */
37
+ export async function getNodesRepresentation(revokedNonces, trees, state) {
18
38
  const nb = new NodesBuilder();
19
39
  if (revokedNonces) {
20
40
  await addRevocationNode(nb, trees, revokedNonces);
@@ -28,15 +48,7 @@ export async function pushHashesToRHS(state, trees, rhsUrl, revokedNonces) {
28
48
  await trees.rootsTree.root()
29
49
  ]));
30
50
  }
31
- if (nb.nodes.length > 0) {
32
- await saveNodes(nb.nodes, rhsUrl);
33
- }
34
- }
35
- async function saveNodes(nodes, nodeUrl) {
36
- const nodesJSON = nodes.map((n) => n.toJSON());
37
- const resp = await fetch(nodeUrl + '/node', { method: 'post', body: JSON.stringify(nodesJSON) });
38
- const status = resp.status;
39
- return status === 200;
51
+ return nb.nodes;
40
52
  }
41
53
  async function addRoRNode(nb, trees) {
42
54
  const currentRootsTree = trees.rootsTree;
@@ -62,8 +74,8 @@ class NodesBuilder {
62
74
  }
63
75
  async addKey(tree, nodeKey) {
64
76
  const { value: nodeValue, siblings } = await tree.get(nodeKey);
65
- const nodeKeyHash = newHashFromBigInt(nodeKey);
66
- const nodeValueHash = newHashFromBigInt(nodeValue);
77
+ const nodeKeyHash = Hash.fromBigInt(nodeKey);
78
+ const nodeValueHash = Hash.fromBigInt(nodeValue);
67
79
  const node = new NodeLeaf(nodeKeyHash, nodeValueHash);
68
80
  const newNodes = await buildNodesUp(siblings, node);
69
81
  for (const n of newNodes) {
@@ -93,7 +105,7 @@ async function buildNodesUp(siblings, node) {
93
105
  nodes[index] = new ProofNode();
94
106
  }
95
107
  nodes[sl].hash = prevHash;
96
- const hashOfOne = newHashFromBigInt(BigInt(1));
108
+ const hashOfOne = Hash.fromBigInt(BigInt(1));
97
109
  nodes[sl].children = [node.entry[0], node.entry[1], hashOfOne];
98
110
  const pathKey = node.entry[0];
99
111
  for (let i = sl - 1; i >= 0; i--) {
@@ -107,7 +119,7 @@ async function buildNodesUp(siblings, node) {
107
119
  nodes[i].children[0] = prevHash;
108
120
  nodes[i].children[1] = siblings[i];
109
121
  }
110
- nodes[i].hash = await hashElems([nodes[i].children[0].bigInt(), nodes[i].children[1].bigInt()]);
122
+ nodes[i].hash = hashElems([nodes[i].children[0].bigInt(), nodes[i].children[1].bigInt()]);
111
123
  prevHash = nodes[i].hash;
112
124
  }
113
125
  return nodes;
@@ -0,0 +1,78 @@
1
+ import { CredentialStatusType } from '../../verifiable';
2
+ /**
3
+ * Registry for managing credential status publishers.
4
+ */
5
+ export class CredentialStatusPublisherRegistry {
6
+ constructor() {
7
+ this._publishers = new Map();
8
+ }
9
+ /**
10
+ * Registers one or more credential status publishers for a given type.
11
+ * @param type - The credential status type.
12
+ * @param publisher - One or more credential status publishers.
13
+ */
14
+ register(type, ...publisher) {
15
+ const publishers = this._publishers.get(type) ?? [];
16
+ publishers.push(...publisher);
17
+ this._publishers.set(type, publishers);
18
+ }
19
+ /**
20
+ * Retrieves the credential status publishers for a given type.
21
+ * @param type - The credential status type.
22
+ * @returns An array of credential status publishers or undefined if none are registered for the given type.
23
+ */
24
+ get(type) {
25
+ return this._publishers.get(type);
26
+ }
27
+ }
28
+ /**
29
+ * Implementation of the ICredentialStatusPublisher interface for publishing on-chain credential status.
30
+ */
31
+ export class Iden3OnchainSmtCredentialStatusPublisher {
32
+ constructor(_storage) {
33
+ this._storage = _storage;
34
+ }
35
+ /**
36
+ * Publishes the credential status to the blockchain.
37
+ * @param params - The parameters for publishing the credential status.
38
+ */
39
+ async publish(params) {
40
+ if (![CredentialStatusType.Iden3OnchainSparseMerkleTreeProof2023].includes(params.credentialStatusType)) {
41
+ throw new Error(`On-chain publishing is not supported for credential status type ${params.credentialStatusType}`);
42
+ }
43
+ const nodesBigInts = params.nodes.map((n) => n.children.map((c) => c.bigInt()));
44
+ const txPromise = this._storage.saveNodes(nodesBigInts);
45
+ if (params.onChain?.txCallback) {
46
+ const cb = params.onChain?.txCallback;
47
+ txPromise.then((receipt) => cb(receipt));
48
+ return;
49
+ }
50
+ await txPromise;
51
+ }
52
+ }
53
+ /**
54
+ * Implementation of the ICredentialStatusPublisher interface for publishing off-chain credential status.
55
+ */
56
+ export class Iden3SmtRhsCredentialStatusPublisher {
57
+ /**
58
+ * Publishes the credential status to a specified node URL.
59
+ * @param params - The parameters for publishing the credential status.
60
+ * @param params.nodes - The proof nodes to be published.
61
+ * @param params.rhsUrl - The URL of the node to publish the credential status to.
62
+ * @returns A promise that resolves when the credential status is successfully published.
63
+ * @throws An error if the publishing fails.
64
+ */
65
+ async publish(params) {
66
+ if (![CredentialStatusType.Iden3ReverseSparseMerkleTreeProof].includes(params.credentialStatusType)) {
67
+ throw new Error(`On-chain publishing is not supported for credential status type ${params.credentialStatusType}`);
68
+ }
69
+ const nodesJSON = params.nodes.map((n) => n.toJSON());
70
+ const resp = await fetch(params.rhsUrl + '/node', {
71
+ method: 'post',
72
+ body: JSON.stringify(nodesJSON)
73
+ });
74
+ if (resp.status !== 200) {
75
+ throw new Error(`Failed to publish credential status. Status: ${resp.status}`);
76
+ }
77
+ }
78
+ }
@@ -1,4 +1,6 @@
1
1
  import { DID } from '@iden3/js-iden3-core';
2
+ import { PublicKey } from '@iden3/js-crypto';
3
+ import { KmsKeyType, keyPath } from '../kms';
2
4
  /**
3
5
  * Retrieves the user DID from a given credential.
4
6
  * If the credential does not have a credentialSubject.id property, the issuer DID is returned.
@@ -17,3 +19,13 @@ export const getUserDIDFromCredential = (issuerDID, credential) => {
17
19
  }
18
20
  return DID.parse(credential.credentialSubject.id);
19
21
  };
22
+ export const getKMSIdByAuthCredential = (credential) => {
23
+ if (!credential.type.includes('AuthBJJCredential')) {
24
+ throw new Error("can't sign with not AuthBJJCredential credential");
25
+ }
26
+ const x = credential.credentialSubject['x'];
27
+ const y = credential.credentialSubject['y'];
28
+ const pb = new PublicKey([BigInt(x), BigInt(y)]);
29
+ const kp = keyPath(KmsKeyType.BabyJubJub, pb.hex());
30
+ return { type: KmsKeyType.BabyJubJub, id: kp };
31
+ };
@@ -5,11 +5,11 @@ import { hashElems, ZERO_HASH } from '@iden3/js-merkletree';
5
5
  import { generateProfileDID, subjectPositionIndex } from './common';
6
6
  import * as uuid from 'uuid';
7
7
  import { Parser, JsonSchemaValidator, cacheLoader } from '../schema-processor';
8
- import { MerkleTreeType } from '../storage/entities/mt';
9
- import { keyPath } from '../kms/provider-helpers';
8
+ import { MerkleTreeType } from '../storage';
10
9
  import { VerifiableConstants, BJJSignatureProof2021, MerklizedRootPosition, SubjectPosition, W3CCredential, Iden3SparseMerkleTreeProof, ProofType, CredentialStatusType } from '../verifiable';
11
- import { pushHashesToRHS } from '../credentials';
10
+ import { getKMSIdByAuthCredential, getNodesRepresentation, pushHashesToRHS } from '../credentials';
12
11
  import { byteEncoder } from '../utils';
12
+ import { CredentialStatusPublisherRegistry, Iden3SmtRhsCredentialStatusPublisher } from '../credentials/status/credential-status-publisher';
13
13
  /**
14
14
  * @public
15
15
  * Wallet instance to manage the digital identity based on iden3 protocol
@@ -30,10 +30,19 @@ export class IdentityWallet {
30
30
  * @param {ICredentialWallet} _credentialWallet - credential wallet instance to quickly access credential CRUD functionality
31
31
  * @public
32
32
  */
33
- constructor(_kms, _storage, _credentialWallet) {
33
+ constructor(_kms, _storage, _credentialWallet, _opts) {
34
34
  this._kms = _kms;
35
35
  this._storage = _storage;
36
36
  this._credentialWallet = _credentialWallet;
37
+ this._opts = _opts;
38
+ if (!_opts?.credentialStatusPublisherRegistry) {
39
+ this._credentialStatusPublisherRegistry = new CredentialStatusPublisherRegistry();
40
+ this._credentialStatusPublisherRegistry.register(CredentialStatusType.Iden3ReverseSparseMerkleTreeProof, new Iden3SmtRhsCredentialStatusPublisher());
41
+ }
42
+ else {
43
+ this._credentialStatusPublisherRegistry = this._opts
44
+ ?.credentialStatusPublisherRegistry;
45
+ }
37
46
  }
38
47
  /**
39
48
  * {@inheritDoc IIdentityWallet.createIdentity}
@@ -107,9 +116,10 @@ export class IdentityWallet {
107
116
  coreClaim: authClaim
108
117
  });
109
118
  credential.proof = [mtpProof];
110
- if (opts.revocationOpts.type === CredentialStatusType.Iden3ReverseSparseMerkleTreeProof) {
111
- await this.publishStateToRHS(did, opts.revocationOpts.id);
112
- }
119
+ await this.publishRevocationInfoByCredentialStatusType(did, opts.revocationOpts.type, {
120
+ rhsUrl: opts.revocationOpts.id,
121
+ onChain: opts.revocationOpts.onChain
122
+ });
113
123
  await this._storage.identity.saveIdentity({
114
124
  did: did.string(),
115
125
  state: currentState,
@@ -171,10 +181,11 @@ export class IdentityWallet {
171
181
  }
172
182
  /** {@inheritDoc IIdentityWallet.getDIDTreeModel} */
173
183
  async getDIDTreeModel(did) {
174
- const claimsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(did.string(), MerkleTreeType.Claims);
175
- const revocationTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(did.string(), MerkleTreeType.Revocations);
176
- const rootsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(did.string(), MerkleTreeType.Roots);
177
- const state = await hashElems([
184
+ const didStr = did.string();
185
+ const claimsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(didStr, MerkleTreeType.Claims);
186
+ const revocationTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(didStr, MerkleTreeType.Revocations);
187
+ const rootsTree = await this._storage.mt.getMerkleTreeByIdentifierAndType(didStr, MerkleTreeType.Roots);
188
+ const state = hashElems([
178
189
  (await claimsTree.root()).bigInt(),
179
190
  (await revocationTree.root()).bigInt(),
180
191
  (await rootsTree.root()).bigInt()
@@ -228,14 +239,14 @@ export class IdentityWallet {
228
239
  }
229
240
  /** {@inheritDoc IIdentityWallet.sign} */
230
241
  async sign(message, credential) {
231
- const keyKMSId = this.getKMSIdByAuthCredential(credential);
242
+ const keyKMSId = getKMSIdByAuthCredential(credential);
232
243
  const payload = poseidon.hashBytes(message);
233
244
  const signature = await this._kms.sign(keyKMSId, BytesHelper.intToBytes(payload));
234
245
  return Signature.newFromCompressed(signature);
235
246
  }
236
247
  /** {@inheritDoc IIdentityWallet.signChallenge} */
237
248
  async signChallenge(challenge, credential) {
238
- const keyKMSId = this.getKMSIdByAuthCredential(credential);
249
+ const keyKMSId = getKMSIdByAuthCredential(credential);
239
250
  const signature = await this._kms.sign(keyKMSId, BytesHelper.intToBytes(challenge));
240
251
  return Signature.newFromCompressed(signature);
241
252
  }
@@ -403,15 +414,35 @@ export class IdentityWallet {
403
414
  rootsTree: treeState.rootsTree
404
415
  }, rhsURL, revokedNonces);
405
416
  }
406
- getKMSIdByAuthCredential(credential) {
407
- if (credential.type.indexOf('AuthBJJCredential') === -1) {
408
- throw new Error("can't sign with not AuthBJJCredential credential");
417
+ /** {@inheritDoc IIdentityWallet.publishRevocationInfoByCredentialStatusType} */
418
+ async publishRevocationInfoByCredentialStatusType(issuerDID, credentialStatusType, opts) {
419
+ const rhsPublishers = this._credentialStatusPublisherRegistry.get(credentialStatusType);
420
+ if (!rhsPublishers) {
421
+ throw new Error(`there is no registered publisher to save hash is not registered for ${credentialStatusType} is not registered`);
422
+ }
423
+ let nodes = [];
424
+ if (opts?.treeModel) {
425
+ nodes = await getNodesRepresentation(opts.revokedNonces, {
426
+ revocationTree: opts.treeModel.revocationTree,
427
+ claimsTree: opts.treeModel.claimsTree,
428
+ state: opts.treeModel.state,
429
+ rootsTree: opts.treeModel.rootsTree
430
+ }, opts.treeModel.state);
431
+ }
432
+ else {
433
+ const treeState = await this.getDIDTreeModel(issuerDID);
434
+ nodes = await getNodesRepresentation(opts?.revokedNonces, {
435
+ revocationTree: treeState.revocationTree,
436
+ claimsTree: treeState.claimsTree,
437
+ state: treeState.state,
438
+ rootsTree: treeState.rootsTree
439
+ }, treeState.state);
440
+ }
441
+ if (!nodes.length) {
442
+ return;
409
443
  }
410
- const x = credential.credentialSubject['x'];
411
- const y = credential.credentialSubject['y'];
412
- const pb = new PublicKey([BigInt(x), BigInt(y)]);
413
- const kp = keyPath(KmsKeyType.BabyJubJub, pb.hex());
414
- return { type: KmsKeyType.BabyJubJub, id: kp };
444
+ const rhsPublishersTask = rhsPublishers.map((publisher) => publisher.publish({ nodes, ...opts, credentialStatusType, issuerDID }));
445
+ await Promise.all(rhsPublishersTask);
415
446
  }
416
447
  async getCoreClaimFromCredential(credential) {
417
448
  const coreClaimFromSigProof = credential.getCoreClaimFromProof(ProofType.BJJSignature);
@@ -1 +1 @@
1
- [{ "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }, { "internalType": "uint64", "name": "nonce", "type": "uint64" }], "name": "getRevocationStatus", "outputs": [{ "components": [{ "components": [{ "internalType": "uint256", "name": "state", "type": "uint256" }, { "internalType": "uint256", "name": "claimsTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "revocationTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "rootOfRoots", "type": "uint256" }], "internalType": "structIOnchainCredentialStatusResolver.IdentityStateRoots", "name": "issuer", "type": "tuple" }, { "components": [{ "internalType": "uint256", "name": "root", "type": "uint256" }, { "internalType": "bool", "name": "existence", "type": "bool" }, { "internalType": "uint256[]", "name": "siblings", "type": "uint256[]" }, { "internalType": "uint256", "name": "index", "type": "uint256" }, { "internalType": "uint256", "name": "value", "type": "uint256" }, { "internalType": "bool", "name": "auxExistence", "type": "bool" }, { "internalType": "uint256", "name": "auxIndex", "type": "uint256" }, { "internalType": "uint256", "name": "auxValue", "type": "uint256" }], "internalType": "structIOnchainCredentialStatusResolver.Proof", "name": "mtp", "type": "tuple" }], "internalType": "structIOnchainCredentialStatusResolver.CredentialStatus", "name": "", "type": "tuple" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }, { "internalType": "uint256", "name": "state", "type": "uint256" }, { "internalType": "uint64", "name": "nonce", "type": "uint64" }], "name": "getRevocationStatusByIdAndState", "outputs": [{ "components": [{ "components": [{ "internalType": "uint256", "name": "state", "type": "uint256" }, { "internalType": "uint256", "name": "claimsTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "revocationTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "rootOfRoots", "type": "uint256" }], "internalType": "structIOnchainCredentialStatusResolver.IdentityStateRoots", "name": "issuer", "type": "tuple" }, { "components": [{ "internalType": "uint256", "name": "root", "type": "uint256" }, { "internalType": "bool", "name": "existence", "type": "bool" }, { "internalType": "uint256[]", "name": "siblings", "type": "uint256[]" }, { "internalType": "uint256", "name": "index", "type": "uint256" }, { "internalType": "uint256", "name": "value", "type": "uint256" }, { "internalType": "bool", "name": "auxExistence", "type": "bool" }, { "internalType": "uint256", "name": "auxIndex", "type": "uint256" }, { "internalType": "uint256", "name": "auxValue", "type": "uint256" }], "internalType": "structIOnchainCredentialStatusResolver.Proof", "name": "mtp", "type": "tuple" }], "internalType": "structIOnchainCredentialStatusResolver.CredentialStatus", "name": "", "type": "tuple" }], "stateMutability": "view", "type": "function" }]
1
+ [{ "inputs": [], "name": "MAX_SMT_DEPTH", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint256", "name": "key", "type": "uint256" }], "name": "getNode", "outputs": [{ "internalType": "uint256[]", "name": "", "type": "uint256[]" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }, { "internalType": "uint64", "name": "nonce", "type": "uint64" }], "name": "getRevocationStatus", "outputs": [{ "components": [{ "components": [{ "internalType": "uint256", "name": "state", "type": "uint256" }, { "internalType": "uint256", "name": "claimsTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "revocationTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "rootOfRoots", "type": "uint256" }], "internalType": "struct IOnchainCredentialStatusResolver.IdentityStateRoots", "name": "issuer", "type": "tuple" }, { "components": [{ "internalType": "uint256", "name": "root", "type": "uint256" }, { "internalType": "bool", "name": "existence", "type": "bool" }, { "internalType": "uint256[]", "name": "siblings", "type": "uint256[]" }, { "internalType": "uint256", "name": "index", "type": "uint256" }, { "internalType": "uint256", "name": "value", "type": "uint256" }, { "internalType": "bool", "name": "auxExistence", "type": "bool" }, { "internalType": "uint256", "name": "auxIndex", "type": "uint256" }, { "internalType": "uint256", "name": "auxValue", "type": "uint256" }], "internalType": "struct IOnchainCredentialStatusResolver.Proof", "name": "mtp", "type": "tuple" }], "internalType": "struct IOnchainCredentialStatusResolver.CredentialStatus", "name": "", "type": "tuple" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint256", "name": "id", "type": "uint256" }, { "internalType": "uint256", "name": "state", "type": "uint256" }, { "internalType": "uint64", "name": "nonce", "type": "uint64" }], "name": "getRevocationStatusByIdAndState", "outputs": [{ "components": [{ "components": [{ "internalType": "uint256", "name": "state", "type": "uint256" }, { "internalType": "uint256", "name": "claimsTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "revocationTreeRoot", "type": "uint256" }, { "internalType": "uint256", "name": "rootOfRoots", "type": "uint256" }], "internalType": "struct IOnchainCredentialStatusResolver.IdentityStateRoots", "name": "issuer", "type": "tuple" }, { "components": [{ "internalType": "uint256", "name": "root", "type": "uint256" }, { "internalType": "bool", "name": "existence", "type": "bool" }, { "internalType": "uint256[]", "name": "siblings", "type": "uint256[]" }, { "internalType": "uint256", "name": "index", "type": "uint256" }, { "internalType": "uint256", "name": "value", "type": "uint256" }, { "internalType": "bool", "name": "auxExistence", "type": "bool" }, { "internalType": "uint256", "name": "auxIndex", "type": "uint256" }, { "internalType": "uint256", "name": "auxValue", "type": "uint256" }], "internalType": "struct IOnchainCredentialStatusResolver.Proof", "name": "mtp", "type": "tuple" }], "internalType": "struct IOnchainCredentialStatusResolver.CredentialStatus", "name": "", "type": "tuple" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint256[][]", "name": "nodes", "type": "uint256[][]" }], "name": "saveNodes", "outputs": [], "stateMutability": "nonpayable", "type": "function" }]
@@ -1,2 +1,3 @@
1
1
  export * from './state';
2
2
  export * from './onchain-zkp-verifier';
3
+ export * from './onchain-revocation';
@@ -16,9 +16,16 @@ export class OnChainRevocationStorage {
16
16
  * @param {string} - onhcain contract address
17
17
  * @param {string} - rpc url to connect to the blockchain
18
18
  */
19
- constructor(config, contractAddress) {
20
- this.provider = new JsonRpcProvider(config.url);
21
- this.onchainContract = new Contract(contractAddress, abi, this.provider);
19
+ constructor(_config, contractAddress, _signer) {
20
+ this._config = _config;
21
+ this._signer = _signer;
22
+ this._provider = new JsonRpcProvider(_config.url);
23
+ let contract = new Contract(contractAddress, abi, this._provider);
24
+ if (this._signer) {
25
+ this._signer = this._signer.connect(this._provider);
26
+ contract = contract.connect(this._signer);
27
+ }
28
+ this._contract = contract;
22
29
  }
23
30
  /**
24
31
  * Get revocation status by issuerId, issuerState and nonce from the onchain.
@@ -26,7 +33,7 @@ export class OnChainRevocationStorage {
26
33
  * @returns Promise<RevocationStatus>
27
34
  */
28
35
  async getRevocationStatusByIdAndState(issuerID, state, nonce) {
29
- const response = await this.onchainContract.getRevocationStatusByIdAndState(issuerID, state, nonce);
36
+ const response = await this._contract.getRevocationStatusByIdAndState(issuerID, state, nonce);
30
37
  const issuer = OnChainRevocationStorage.convertIssuerInfo(response.issuer);
31
38
  const mtp = OnChainRevocationStorage.convertSmtProofToProof(response.mtp);
32
39
  return {
@@ -40,7 +47,7 @@ export class OnChainRevocationStorage {
40
47
  * @returns Promise<RevocationStatus>
41
48
  */
42
49
  async getRevocationStatus(issuerID, nonce) {
43
- const response = await this.onchainContract.getRevocationStatus(issuerID, nonce);
50
+ const response = await this._contract.getRevocationStatus(issuerID, nonce);
44
51
  const issuer = OnChainRevocationStorage.convertIssuerInfo(response.issuer);
45
52
  const mtp = OnChainRevocationStorage.convertSmtProofToProof(response.mtp);
46
53
  return {
@@ -48,6 +55,39 @@ export class OnChainRevocationStorage {
48
55
  mtp
49
56
  };
50
57
  }
58
+ async saveNodes(payload) {
59
+ if (!this._signer) {
60
+ throw new Error('No signer provided');
61
+ }
62
+ const feeData = await this._provider.getFeeData();
63
+ const maxFeePerGas = this._config.maxFeePerGas
64
+ ? BigInt(this._config.maxFeePerGas)
65
+ : feeData.maxFeePerGas;
66
+ const maxPriorityFeePerGas = this._config.maxPriorityFeePerGas
67
+ ? BigInt(this._config.maxPriorityFeePerGas)
68
+ : feeData.maxPriorityFeePerGas;
69
+ const gasLimit = await this._contract.saveNodes.estimateGas(payload);
70
+ const txData = await this._contract.saveNodes.populateTransaction(payload);
71
+ const request = {
72
+ to: txData.to,
73
+ data: txData.data,
74
+ gasLimit,
75
+ maxFeePerGas,
76
+ maxPriorityFeePerGas
77
+ };
78
+ const tx = await this._signer.sendTransaction(request);
79
+ return tx.wait().then((txReceipt) => {
80
+ if (!txReceipt) {
81
+ throw new Error(`transaction: ${tx.hash} failed to mine`);
82
+ }
83
+ const status = txReceipt.status;
84
+ const txnHash = txReceipt.hash;
85
+ if (!status) {
86
+ throw new Error(`transaction: ${txnHash} failed to mine`);
87
+ }
88
+ return txReceipt;
89
+ });
90
+ }
51
91
  static convertIssuerInfo(issuer) {
52
92
  const [state, claimsTreeRoot, revocationTreeRoot, rootOfRoots] = issuer.map((i) => Hash.fromBigInt(i).hex());
53
93
  return {
@@ -3,6 +3,7 @@ export * from './status/reverse-sparse-merkle-tree';
3
3
  export * from './status/sparse-merkle-tree';
4
4
  export * from './status/resolver';
5
5
  export * from './status/agent-revocation';
6
+ export * from './status/credential-status-publisher';
6
7
  export * from './status/utils';
7
8
  export * from './credential-wallet';
8
9
  export * from './rhs';
@@ -1,4 +1,5 @@
1
1
  import { Hash, Merkletree } from '@iden3/js-merkletree';
2
+ import { ProofNode } from './status/reverse-sparse-merkle-tree';
2
3
  /**
3
4
  * Interface to unite contains three trees: claim, revocation and rootOfRoots
4
5
  * Also contains the current state of identity
@@ -17,6 +18,7 @@ export interface TreesModel {
17
18
  * A reverse hash service (RHS) is a centralized or decentralized service for storing publicly available data about identity.
18
19
  * Such data are identity state and state of revocation tree and roots tree root tree.
19
20
  *
21
+ * @deprecated Use `pushHashesToReverseHashService` instead.
20
22
  * @param {Hash} state - current state of identity
21
23
  * @param {TreesModel} trees - current trees of identity (claims, revocation, rootOfRoots )
22
24
  * @param {string} rhsUrl - URL of service
@@ -24,3 +26,12 @@ export interface TreesModel {
24
26
  * @returns void
25
27
  */
26
28
  export declare function pushHashesToRHS(state: Hash, trees: TreesModel, rhsUrl: string, revokedNonces?: number[]): Promise<void>;
29
+ /**
30
+ * Retrieves the representation of nodes for generating a proof.
31
+ *
32
+ * @param revokedNonces - An array of revoked nonces.
33
+ * @param trees - The TreesModel object containing the necessary trees.
34
+ * @param state - The hash of the state.
35
+ * @returns A Promise that resolves to an array of ProofNode objects.
36
+ */
37
+ export declare function getNodesRepresentation(revokedNonces: number[] | undefined, trees: TreesModel, state: Hash): Promise<ProofNode[]>;
@@ -0,0 +1,70 @@
1
+ import { TransactionReceipt } from 'ethers';
2
+ import { JSONObject } from '../../iden3comm';
3
+ import { OnChainRevocationStorage } from '../../storage';
4
+ import { CredentialStatusType } from '../../verifiable';
5
+ import { ProofNode } from './reverse-sparse-merkle-tree';
6
+ /**
7
+ * Represents a credential status publisher.
8
+ */
9
+ export interface ICredentialStatusPublisher {
10
+ /**
11
+ * Publishes the credential status.
12
+ * @param params - The parameters for publishing the status.
13
+ * @returns A promise that resolves when the status is published.
14
+ */
15
+ publish(params: JSONObject): Promise<void>;
16
+ }
17
+ /**
18
+ * Registry for managing credential status publishers.
19
+ */
20
+ export declare class CredentialStatusPublisherRegistry {
21
+ private _publishers;
22
+ /**
23
+ * Registers one or more credential status publishers for a given type.
24
+ * @param type - The credential status type.
25
+ * @param publisher - One or more credential status publishers.
26
+ */
27
+ register(type: CredentialStatusType, ...publisher: ICredentialStatusPublisher[]): void;
28
+ /**
29
+ * Retrieves the credential status publishers for a given type.
30
+ * @param type - The credential status type.
31
+ * @returns An array of credential status publishers or undefined if none are registered for the given type.
32
+ */
33
+ get(type: CredentialStatusType): ICredentialStatusPublisher[] | undefined;
34
+ }
35
+ /**
36
+ * Implementation of the ICredentialStatusPublisher interface for publishing on-chain credential status.
37
+ */
38
+ export declare class Iden3OnchainSmtCredentialStatusPublisher implements ICredentialStatusPublisher {
39
+ private readonly _storage;
40
+ constructor(_storage: OnChainRevocationStorage);
41
+ /**
42
+ * Publishes the credential status to the blockchain.
43
+ * @param params - The parameters for publishing the credential status.
44
+ */
45
+ publish(params: {
46
+ nodes: ProofNode[];
47
+ credentialStatusType: CredentialStatusType;
48
+ onChain?: {
49
+ txCallback?: (tx: TransactionReceipt) => Promise<void>;
50
+ };
51
+ }): Promise<void>;
52
+ }
53
+ /**
54
+ * Implementation of the ICredentialStatusPublisher interface for publishing off-chain credential status.
55
+ */
56
+ export declare class Iden3SmtRhsCredentialStatusPublisher implements ICredentialStatusPublisher {
57
+ /**
58
+ * Publishes the credential status to a specified node URL.
59
+ * @param params - The parameters for publishing the credential status.
60
+ * @param params.nodes - The proof nodes to be published.
61
+ * @param params.rhsUrl - The URL of the node to publish the credential status to.
62
+ * @returns A promise that resolves when the credential status is successfully published.
63
+ * @throws An error if the publishing fails.
64
+ */
65
+ publish(params: {
66
+ nodes: ProofNode[];
67
+ credentialStatusType: CredentialStatusType;
68
+ rhsUrl: string;
69
+ }): Promise<void>;
70
+ }
@@ -1,5 +1,6 @@
1
1
  import { DID } from '@iden3/js-iden3-core';
2
2
  import { W3CCredential } from '../verifiable';
3
+ import { KmsKeyId } from '../kms';
3
4
  /**
4
5
  * Retrieves the user DID from a given credential.
5
6
  * If the credential does not have a credentialSubject.id property, the issuer DID is returned.
@@ -10,3 +11,4 @@ import { W3CCredential } from '../verifiable';
10
11
  * @throws Error if the credentialSubject.id is not a string.
11
12
  */
12
13
  export declare const getUserDIDFromCredential: (issuerDID: DID, credential: W3CCredential) => DID;
14
+ export declare const getKMSIdByAuthCredential: (credential: W3CCredential) => KmsKeyId;