@0xpolygonid/js-sdk 1.23.0 → 1.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/browser/esm/index.js +2573 -392
  2. package/dist/browser/esm/index.js.map +1 -1
  3. package/dist/browser/umd/index.js +2575 -390
  4. package/dist/browser/umd/index.js.map +1 -1
  5. package/dist/node/cjs/circuits/auth-v2.js +6 -0
  6. package/dist/node/cjs/credentials/credential-wallet.js +11 -78
  7. package/dist/node/cjs/credentials/index.js +1 -0
  8. package/dist/node/cjs/credentials/status/did-resolver-revocation.js +21 -0
  9. package/dist/node/cjs/iden3comm/handlers/contract-request.js +7 -1
  10. package/dist/node/cjs/iden3comm/handlers/fetch.js +32 -0
  11. package/dist/node/cjs/iden3comm/handlers/payment.js +30 -24
  12. package/dist/node/cjs/iden3comm/utils/contract-request.utils.js +59 -0
  13. package/dist/node/cjs/iden3comm/utils/index.js +1 -0
  14. package/dist/node/cjs/proof/proof-service.js +6 -0
  15. package/dist/node/cjs/storage/blockchain/abi/ERC20.json +1 -0
  16. package/dist/node/cjs/storage/blockchain/did-resolver-readonly-storage.js +72 -0
  17. package/dist/node/cjs/storage/blockchain/{erc20-permit-sig.js → erc20-helper.js} +14 -1
  18. package/dist/node/cjs/storage/blockchain/index.js +3 -1
  19. package/dist/node/cjs/storage/blockchain/onchain-issuer-adapter/non-merklized/version/v0.0.1/onchain-non-merklized-issuer-adapter.js +245 -0
  20. package/dist/node/cjs/storage/blockchain/onchain-issuer.js +82 -0
  21. package/dist/node/cjs/storage/blockchain/onchain-zkp-verifier.js +90 -77
  22. package/dist/node/cjs/storage/interfaces/index.js +1 -0
  23. package/dist/node/cjs/storage/interfaces/onchain-issuer.js +2 -0
  24. package/dist/node/cjs/utils/did-helper.js +11 -6
  25. package/dist/node/cjs/verifiable/constants.js +2 -2
  26. package/dist/node/cjs/verifiable/credential.js +86 -0
  27. package/dist/node/esm/circuits/auth-v2.js +6 -0
  28. package/dist/node/esm/credentials/credential-wallet.js +12 -79
  29. package/dist/node/esm/credentials/index.js +1 -0
  30. package/dist/node/esm/credentials/status/did-resolver-revocation.js +17 -0
  31. package/dist/node/esm/iden3comm/handlers/contract-request.js +7 -1
  32. package/dist/node/esm/iden3comm/handlers/fetch.js +32 -0
  33. package/dist/node/esm/iden3comm/handlers/payment.js +30 -24
  34. package/dist/node/esm/iden3comm/utils/contract-request.utils.js +54 -0
  35. package/dist/node/esm/iden3comm/utils/index.js +1 -0
  36. package/dist/node/esm/proof/proof-service.js +6 -0
  37. package/dist/node/esm/storage/blockchain/abi/ERC20.json +1 -0
  38. package/dist/node/esm/storage/blockchain/did-resolver-readonly-storage.js +68 -0
  39. package/dist/node/esm/storage/blockchain/{erc20-permit-sig.js → erc20-helper.js} +14 -2
  40. package/dist/node/esm/storage/blockchain/index.js +3 -1
  41. package/dist/node/esm/storage/blockchain/onchain-issuer-adapter/non-merklized/version/v0.0.1/onchain-non-merklized-issuer-adapter.js +241 -0
  42. package/dist/node/esm/storage/blockchain/onchain-issuer.js +78 -0
  43. package/dist/node/esm/storage/blockchain/onchain-zkp-verifier.js +92 -79
  44. package/dist/node/esm/storage/interfaces/index.js +1 -0
  45. package/dist/node/esm/storage/interfaces/onchain-issuer.js +1 -0
  46. package/dist/node/esm/utils/did-helper.js +11 -6
  47. package/dist/node/esm/verifiable/constants.js +2 -2
  48. package/dist/node/esm/verifiable/credential.js +88 -2
  49. package/dist/types/circuits/auth-v2.d.ts +3 -2
  50. package/dist/types/credentials/credential-wallet.d.ts +0 -6
  51. package/dist/types/credentials/index.d.ts +1 -0
  52. package/dist/types/credentials/models.d.ts +8 -0
  53. package/dist/types/credentials/status/did-resolver-revocation.d.ts +7 -0
  54. package/dist/types/iden3comm/handlers/fetch.d.ts +8 -0
  55. package/dist/types/iden3comm/handlers/payment.d.ts +7 -10
  56. package/dist/types/iden3comm/types/protocol/payment.d.ts +6 -5
  57. package/dist/types/iden3comm/utils/contract-request.utils.d.ts +20 -0
  58. package/dist/types/iden3comm/utils/index.d.ts +1 -0
  59. package/dist/types/proof/proof-service.d.ts +10 -0
  60. package/dist/types/storage/blockchain/did-resolver-readonly-storage.d.ts +16 -0
  61. package/dist/types/storage/blockchain/{erc20-permit-sig.d.ts → erc20-helper.d.ts} +8 -1
  62. package/dist/types/storage/blockchain/index.d.ts +3 -1
  63. package/dist/types/storage/blockchain/onchain-issuer-adapter/non-merklized/version/v0.0.1/onchain-non-merklized-issuer-adapter.d.ts +66 -0
  64. package/dist/types/storage/blockchain/onchain-issuer.d.ts +40 -0
  65. package/dist/types/storage/blockchain/onchain-zkp-verifier.d.ts +13 -12
  66. package/dist/types/storage/entities/state.d.ts +2 -0
  67. package/dist/types/storage/interfaces/index.d.ts +1 -0
  68. package/dist/types/storage/interfaces/onchain-issuer.d.ts +12 -0
  69. package/dist/types/verifiable/constants.d.ts +2 -2
  70. package/dist/types/verifiable/credential.d.ts +15 -2
  71. package/package.json +3 -2
@@ -0,0 +1,241 @@
1
+ import { Claim, DID, Id } from '@iden3/js-iden3-core';
2
+ import { NonMerklizedIssuerBase__factory } from '@iden3/onchain-non-merklized-issuer-base-abi';
3
+ import { CredentialStatusType, DisplayMethodType, Iden3SparseMerkleTreeProof, W3CCredential } from '../../../../../../verifiable';
4
+ import { Merklizer, Path } from '@iden3/js-jsonld-merklization';
5
+ import { XSDNS } from '../../../../../../circuits';
6
+ import { Hash, Proof } from '@iden3/js-merkletree';
7
+ import { ethers } from 'ethers';
8
+ import { getDateFromUnixTimestamp } from '@iden3/js-iden3-core';
9
+ var NonMerklizedIssuerInterfaces;
10
+ (function (NonMerklizedIssuerInterfaces) {
11
+ NonMerklizedIssuerInterfaces["InterfaceDetection"] = "0x01ffc9a7";
12
+ NonMerklizedIssuerInterfaces["InterfaceNonMerklizedIssuer"] = "0x58874949";
13
+ NonMerklizedIssuerInterfaces["InterfaceGetCredential"] = "0x5d1ca631";
14
+ })(NonMerklizedIssuerInterfaces || (NonMerklizedIssuerInterfaces = {}));
15
+ var ValueHashes;
16
+ (function (ValueHashes) {
17
+ ValueHashes["BooleanTrue"] = "18586133768512220936620570745912940619677854269274689475585506675881198879027";
18
+ ValueHashes["BooleanFalse"] = "19014214495641488759237505126948346942972912379615652741039992445865937985820";
19
+ })(ValueHashes || (ValueHashes = {}));
20
+ /**
21
+ * `OnchainNonMerklizedIssuerAdapter` provides functionality to interact with a non-merklized on-chain credential issuer.
22
+ * This adapter enables interface detection, credential retrieval, and conversion to the W3C Verifiable Credential format.
23
+ *
24
+ * @public
25
+ * @beta
26
+ * @class OnchainNonMerklizedIssuerAdapter
27
+ */
28
+ export class OnchainNonMerklizedIssuerAdapter {
29
+ /**
30
+ * Initializes an instance of `OnchainNonMerklizedIssuerAdapter`.
31
+ *
32
+ * @param ethConnectionConfig The configuration for the Ethereum connection.
33
+ * @param issuerDid The decentralized identifier (DID) of the issuer.
34
+ * @param merklizationOptions Optional settings for merklization.
35
+ */
36
+ constructor(ethConnectionConfig, issuerDid, options) {
37
+ if (!ethConnectionConfig.chainId) {
38
+ throw new Error('Chain ID is required');
39
+ }
40
+ this._chainId = ethConnectionConfig.chainId;
41
+ this._contractAddress = ethers.getAddress(ethers.hexlify(Id.ethAddressFromId(DID.idFromDID(issuerDid))));
42
+ this._contract = NonMerklizedIssuerBase__factory.connect(this._contractAddress, new ethers.JsonRpcProvider(ethConnectionConfig.url));
43
+ this._issuerDid = issuerDid;
44
+ this._merklizationOptions = options?.merklizationOptions;
45
+ }
46
+ /**
47
+ * Checks if the contract supports required interfaces.
48
+ * Throws an error if any required interface is unsupported.
49
+ *
50
+ * @throws Error - If required interfaces are not supported.
51
+ */
52
+ async isInterfaceSupported() {
53
+ const supportedInterfaces = [
54
+ {
55
+ name: 'Interface detection ERC-165',
56
+ value: NonMerklizedIssuerInterfaces.InterfaceDetection
57
+ },
58
+ {
59
+ name: 'Interface non-merklized issuer',
60
+ value: NonMerklizedIssuerInterfaces.InterfaceNonMerklizedIssuer
61
+ },
62
+ {
63
+ name: 'Interface get credential',
64
+ value: NonMerklizedIssuerInterfaces.InterfaceGetCredential
65
+ }
66
+ ];
67
+ const unsupportedInterfaces = await Promise.all(supportedInterfaces.map(async (interfaceObj) => {
68
+ const isSupported = await this._contract.supportsInterface(interfaceObj.value);
69
+ return isSupported ? null : interfaceObj.name;
70
+ }));
71
+ const unsupportedInterfacesFiltered = unsupportedInterfaces.filter((interfaceName) => interfaceName !== null);
72
+ if (unsupportedInterfacesFiltered.length > 0) {
73
+ throw new Error(`Unsupported interfaces: ${unsupportedInterfacesFiltered.join(', ')}`);
74
+ }
75
+ }
76
+ /**
77
+ * Retrieves a credential from the on-chain non-merklized contract.
78
+ * @param userId The user's core.Id.
79
+ * @param credentialId The unique identifier of the credential.
80
+ */
81
+ async getCredential(userId, credentialId) {
82
+ const [credentialData, coreClaimBigInts, credentialSubjectFields] = await this._contract.getCredential(userId.bigInt(), credentialId);
83
+ return { credentialData, coreClaimBigInts, credentialSubjectFields };
84
+ }
85
+ /**
86
+ * Retrieves the credential IDs of a user.
87
+ * @param userId The user's core.Id.
88
+ * @returns An array of credential IDs.
89
+ */
90
+ async getUserCredentialsIds(userId) {
91
+ return this._contract.getUserCredentialIds(userId.bigInt());
92
+ }
93
+ /**
94
+ * Converts on-chain credential to a verifiable credential.
95
+ *
96
+ * @param credentialData Data structure of the credential from the contract.
97
+ * @param coreClaimBigInts Claim data in bigint format.
98
+ * @param credentialSubjectFields Subject fields of the credential.
99
+ */
100
+ async convertOnChainInfoToW3CCredential(credentialData, coreClaimBigInts, credentialSubjectFields) {
101
+ const c = new Claim().unMarshalJson(JSON.stringify(coreClaimBigInts.map((b) => b.toString())));
102
+ const credentialSubject = await this.convertCredentialSubject(c, credentialData.context, credentialData._type, credentialSubjectFields);
103
+ const credentialRequest = {
104
+ id: this.credentialId(credentialData.id),
105
+ credentialSchema: credentialData.credentialSchema.id,
106
+ type: credentialData._type,
107
+ credentialSubject: credentialSubject,
108
+ expiration: c.getExpirationDate()?.getTime(),
109
+ displayMethod: this.convertDisplayMethod(credentialData.displayMethod),
110
+ context: credentialData.context,
111
+ revocationOpts: {
112
+ id: this._contractAddress,
113
+ nonce: Number(c.getRevocationNonce()),
114
+ type: CredentialStatusType.Iden3OnchainSparseMerkleTreeProof2023
115
+ },
116
+ issuanceDate: getDateFromUnixTimestamp(Number(credentialData.issuanceDate)).getTime()
117
+ };
118
+ const existenceProof = await this.existenceProof(c);
119
+ const w3c = W3CCredential.fromCredentialRequest(this._issuerDid, credentialRequest);
120
+ w3c.proof = [existenceProof];
121
+ return w3c;
122
+ }
123
+ credentialId(id) {
124
+ return `urn:iden3:onchain:${this._chainId}:${this._contractAddress}:${id}`;
125
+ }
126
+ async convertCredentialSubject(coreClaim, contractContexts, credentialType, credentialSubjectFields) {
127
+ const contractContextsStr = JSON.stringify({
128
+ '@context': contractContexts
129
+ });
130
+ const credentialSubject = {};
131
+ for (const f of credentialSubjectFields) {
132
+ const dataType = await Path.newTypeFromContext(contractContextsStr, `${credentialType}.${f.key}`, this._merklizationOptions);
133
+ switch (dataType) {
134
+ case XSDNS.Boolean: {
135
+ switch (f.rawValue.toString()) {
136
+ case ValueHashes.BooleanTrue:
137
+ credentialSubject[f.key] = true;
138
+ break;
139
+ case ValueHashes.BooleanFalse:
140
+ credentialSubject[f.key] = false;
141
+ break;
142
+ }
143
+ break;
144
+ }
145
+ case (XSDNS.NonNegativeInteger,
146
+ XSDNS.NonPositiveInteger,
147
+ XSDNS.NegativeInteger,
148
+ XSDNS.PositiveInteger):
149
+ {
150
+ credentialSubject[f.key] = f.value.toString();
151
+ break;
152
+ }
153
+ case XSDNS.Integer: {
154
+ credentialSubject[f.key] = Number(f.value);
155
+ break;
156
+ }
157
+ case XSDNS.String: {
158
+ this.validateSourceValue(dataType, f.value, f.rawValue);
159
+ credentialSubject[f.key] = f.rawValue;
160
+ break;
161
+ }
162
+ case XSDNS.DateTime: {
163
+ const timestamp = BigInt(f.rawValue);
164
+ const sourceTimestamp = getDateFromUnixTimestamp(Number(timestamp)).toISOString();
165
+ this.validateSourceValue(dataType, f.value, sourceTimestamp);
166
+ credentialSubject[f.key] = sourceTimestamp;
167
+ break;
168
+ }
169
+ case XSDNS.Double: {
170
+ const rawFloat = Number(f.rawValue);
171
+ this.validateSourceValue(dataType, f.value, rawFloat);
172
+ credentialSubject[f.key] = rawFloat;
173
+ break;
174
+ }
175
+ default: {
176
+ throw new Error(`Unsupported data type ${dataType}`);
177
+ }
178
+ }
179
+ }
180
+ credentialSubject['type'] = credentialType;
181
+ const subjectId = coreClaim.getId();
182
+ const subjectDid = DID.parseFromId(subjectId);
183
+ credentialSubject['id'] = subjectDid.string();
184
+ return credentialSubject;
185
+ }
186
+ async existenceProof(coreClaim) {
187
+ const [mtpProof, stateInfo] = await this._contract.getClaimProofWithStateInfo(coreClaim.hIndex());
188
+ if (!mtpProof.existence) {
189
+ throw new Error('Claim does not exist');
190
+ }
191
+ const latestStateHash = Hash.fromBigInt(stateInfo.state);
192
+ const latestClaimsOfRootHash = Hash.fromBigInt(stateInfo.claimsRoot);
193
+ const latestRevocationOfRootHash = Hash.fromBigInt(stateInfo.revocationsRoot);
194
+ const latestRootsOfRootHash = Hash.fromBigInt(stateInfo.rootsRoot);
195
+ const p = new Proof({
196
+ siblings: mtpProof.siblings.map((s) => Hash.fromBigInt(s)),
197
+ existence: mtpProof.existence,
198
+ nodeAux: mtpProof.auxExistence
199
+ ? {
200
+ key: Hash.fromBigInt(mtpProof.auxIndex),
201
+ value: Hash.fromBigInt(mtpProof.auxValue)
202
+ }
203
+ : undefined
204
+ });
205
+ return new Iden3SparseMerkleTreeProof({
206
+ issuerData: {
207
+ id: this._issuerDid,
208
+ state: {
209
+ value: latestStateHash,
210
+ claimsTreeRoot: latestClaimsOfRootHash,
211
+ revocationTreeRoot: latestRevocationOfRootHash,
212
+ rootOfRoots: latestRootsOfRootHash
213
+ }
214
+ },
215
+ mtp: p,
216
+ coreClaim: coreClaim
217
+ });
218
+ }
219
+ async validateSourceValue(dataType, originHash, source) {
220
+ const sourceHash = await Merklizer.hashValue(dataType, source);
221
+ if (sourceHash !== originHash) {
222
+ throw new Error(`Invalid source value for ${dataType} type`);
223
+ }
224
+ }
225
+ convertDisplayMethod(onchainDisplayMethod) {
226
+ if (!onchainDisplayMethod.id || !onchainDisplayMethod._type) {
227
+ return undefined;
228
+ }
229
+ switch (onchainDisplayMethod._type) {
230
+ case DisplayMethodType.Iden3BasicDisplayMethodV1: {
231
+ return {
232
+ id: onchainDisplayMethod.id,
233
+ type: DisplayMethodType.Iden3BasicDisplayMethodV1
234
+ };
235
+ }
236
+ default: {
237
+ throw new Error(`Unsupported display method type ${onchainDisplayMethod._type}`);
238
+ }
239
+ }
240
+ }
241
+ }
@@ -0,0 +1,78 @@
1
+ import { DID, Id, chainIDfromDID } from '@iden3/js-iden3-core';
2
+ import { Contract, ethers } from 'ethers';
3
+ import { INonMerklizedIssuerABI as abi } from '@iden3/onchain-non-merklized-issuer-base-abi';
4
+ import { OnchainNonMerklizedIssuerAdapter } from './onchain-issuer-adapter/non-merklized/version/v0.0.1/onchain-non-merklized-issuer-adapter';
5
+ /**
6
+ * Represents an adapter for interacting with on-chain issuers.
7
+ *
8
+ * @public
9
+ * @beta
10
+ * @class OnchainIssuer
11
+ */
12
+ export class OnchainIssuer {
13
+ /**
14
+ * Initializes an instance of `Adapter`.
15
+ * @param config The configuration for the Ethereum connection.
16
+ * @param merklizationOptions Optional settings for merklization.
17
+ */
18
+ constructor(config, options) {
19
+ this._ethConnectionConfig = config;
20
+ this._onchainIssuerOptions = options;
21
+ }
22
+ /**
23
+ * Retrieves a credential from the on-chain issuer.
24
+ * @param issuerDID The issuer's core.DID.
25
+ * @param userId The user's core.Id.
26
+ * @param credentialId The unique identifier of the credential.
27
+ */
28
+ async getCredential(issuerDID, userDID, credentialId) {
29
+ const { contract, connection } = this.getContractConnection(issuerDID);
30
+ const response = await contract.getCredentialAdapterVersion();
31
+ switch (response) {
32
+ case '0.0.1': {
33
+ const adapter = new OnchainNonMerklizedIssuerAdapter(connection, issuerDID, {
34
+ merklizationOptions: this._onchainIssuerOptions?.merklizationOptions
35
+ });
36
+ await adapter.isInterfaceSupported();
37
+ const { credentialData, coreClaimBigInts, credentialSubjectFields } = await adapter.getCredential(DID.idFromDID(userDID), credentialId);
38
+ return await adapter.convertOnChainInfoToW3CCredential(credentialData, coreClaimBigInts, credentialSubjectFields);
39
+ }
40
+ default:
41
+ throw new Error(`Unsupported adapter version ${response}`);
42
+ }
43
+ }
44
+ /**
45
+ * Retrieves the credential identifiers for a user from the on-chain issuer.
46
+ * @param issuerDID The issuer's core.DID.
47
+ * @param userId The user's core.Id.
48
+ */
49
+ async getUserCredentialIds(issuerDID, userDID) {
50
+ const { contract, connection } = this.getContractConnection(issuerDID);
51
+ const response = await contract.getCredentialAdapterVersion();
52
+ switch (response) {
53
+ case '0.0.1': {
54
+ const adapter = new OnchainNonMerklizedIssuerAdapter(connection, issuerDID, {
55
+ merklizationOptions: this._onchainIssuerOptions?.merklizationOptions
56
+ });
57
+ await adapter.isInterfaceSupported();
58
+ return await adapter.getUserCredentialsIds(DID.idFromDID(userDID));
59
+ }
60
+ default:
61
+ throw new Error(`Unsupported adapter version ${response}`);
62
+ }
63
+ }
64
+ getContractConnection(did) {
65
+ const issuerId = DID.idFromDID(did);
66
+ const chainId = chainIDfromDID(did);
67
+ const contractAddress = ethers.getAddress(ethers.hexlify(Id.ethAddressFromId(issuerId)));
68
+ const connection = this._ethConnectionConfig.find((c) => c.chainId === chainId);
69
+ if (!connection) {
70
+ throw new Error(`No connection found for chain ID ${chainId}`);
71
+ }
72
+ if (!connection.url) {
73
+ throw new Error(`No URL found for chain ID ${chainId}`);
74
+ }
75
+ const contract = new Contract(contractAddress, abi, new ethers.JsonRpcProvider(connection.url));
76
+ return { contract, connection };
77
+ }
78
+ }
@@ -1,10 +1,11 @@
1
1
  import { JsonRpcProvider, Contract, ethers } from 'ethers';
2
2
  import abi from './abi/ZkpVerifier.json';
3
3
  import { TransactionService } from '../../blockchain';
4
- import { DID } from '@iden3/js-iden3-core';
5
- import { AtomicQueryMTPV2OnChainPubSignals, AtomicQuerySigV2OnChainPubSignals, AtomicQueryV3OnChainPubSignals, CircuitId } from '../../circuits';
4
+ import { chainIDfromDID, DID, Id } from '@iden3/js-iden3-core';
5
+ import { AtomicQueryMTPV2OnChainPubSignals, AtomicQuerySigV2OnChainPubSignals, AtomicQueryV3OnChainPubSignals, AuthV2PubSignals, CircuitId } from '../../circuits';
6
6
  import { byteEncoder, DIDDocumentSignature, resolveDidDocument } from '../../utils';
7
7
  import { poseidon } from '@iden3/js-crypto';
8
+ import { Hash } from '@iden3/js-merkletree';
8
9
  const maxGasLimit = 10000000n;
9
10
  /**
10
11
  * Supported function signature for SubmitZKPResponse
@@ -37,23 +38,8 @@ export class OnChainZKPVerifier {
37
38
  constructor(_configs, _opts) {
38
39
  this._configs = _configs;
39
40
  this._opts = _opts;
40
- /**
41
- * supported circuits
42
- */
43
- this._supportedCircuits = [
44
- CircuitId.AtomicQueryMTPV2OnChain,
45
- CircuitId.AtomicQuerySigV2OnChain,
46
- CircuitId.AtomicQueryV3OnChain
47
- ];
48
- /**
49
- * abi coder to encode/decode structures to solidity bytes
50
- */
51
- this._abiCoder = new ethers.AbiCoder();
52
41
  }
53
- /**
54
- * {@inheritDoc IOnChainZKPVerifier.prepareTxArgsSubmitV1}
55
- */
56
- async prepareTxArgsSubmitV1(txData, zkProofResponse) {
42
+ static async prepareTxArgsSubmitV1(txData, zkProofResponse) {
57
43
  if (txData.method_id.replace('0x', '') !== FunctionSignatures.SubmitZKPResponseV1) {
58
44
  throw new Error(`prepareTxArgsSubmitV1 function doesn't implement requested method id. Only '0x${FunctionSignatures.SubmitZKPResponseV1}' is supported.`);
59
45
  }
@@ -71,6 +57,12 @@ export class OnChainZKPVerifier {
71
57
  ];
72
58
  return payload;
73
59
  }
60
+ /**
61
+ * {@inheritDoc IOnChainZKPVerifier.prepareTxArgsSubmitV1}
62
+ */
63
+ async prepareTxArgsSubmitV1(txData, zkProofResponse) {
64
+ return OnChainZKPVerifier.prepareTxArgsSubmitV1(txData, zkProofResponse);
65
+ }
74
66
  /**
75
67
  * {@inheritDoc IOnChainZKPVerifier.submitZKPResponse}
76
68
  */
@@ -160,55 +152,60 @@ export class OnChainZKPVerifier {
160
152
  const { txnHash } = await transactionService.sendTransactionRequest(ethSigner, request);
161
153
  return new Map().set(txnHash, zkProofResponses);
162
154
  }
163
- async prepareTxArgsSubmitV2(txData, zkProofResponses) {
155
+ static getCrossChainResolvers(source, txDataChainId, type, didResolverUrl) {
156
+ return [
157
+ ...new Set(source.map((info) => JSON.stringify({
158
+ id: info.id.string(),
159
+ [type]: type === 'gist' ? info.root?.string() : info.state?.string()
160
+ })))
161
+ ].reduce((acc, s) => {
162
+ const info = JSON.parse(s);
163
+ const id = Id.fromString(info.id);
164
+ const chainId = chainIDfromDID(DID.parseFromId(id));
165
+ if (txDataChainId === chainId) {
166
+ return acc;
167
+ }
168
+ const promise = this.resolveDidDocumentEip712MessageAndSignature(DID.parseFromId(Id.fromString(info.id)), didResolverUrl, {
169
+ [type]: Hash.fromString(info[type])
170
+ });
171
+ return [...acc, promise];
172
+ }, []);
173
+ }
174
+ static async prepareTxArgsSubmitV2(resolverUrl, txData, zkProofResponses) {
164
175
  if (txData.method_id.replace('0x', '') !== FunctionSignatures.SubmitZKPResponseV2) {
165
176
  throw new Error(`submit cross chain doesn't implement requested method id. Only '0x${FunctionSignatures.SubmitZKPResponseV2}' is supported.`);
166
177
  }
167
- if (!this._opts?.didResolverUrl) {
168
- throw new Error(`did resolver url required for crosschain verification`);
169
- }
170
- const gistUpdateArr = [];
171
- const stateUpdateArr = [];
178
+ const gistUpdates = [];
179
+ const stateUpdates = [];
172
180
  const payload = [];
173
- // Resolved gists and states to avoid duplicate requests
174
- const gistUpdateResolutionsPending = [];
175
- const stateUpdateResolutionsPending = [];
181
+ const emptyBytes = '0x';
176
182
  for (const zkProof of zkProofResponses) {
177
- const requestID = zkProof.id;
178
- const inputs = zkProof.pub_signals;
179
- if (!this._supportedCircuits.includes(zkProof.circuitId)) {
183
+ const { id: requestId, pub_signals: inputs } = zkProof;
184
+ const proofCircuitId = zkProof.circuitId;
185
+ if (!this._supportedCircuits.includes(proofCircuitId)) {
180
186
  throw new Error(`Circuit ${zkProof.circuitId} not supported by OnChainZKPVerifier`);
181
187
  }
188
+ if (inputs.length === 0) {
189
+ payload.push({
190
+ requestId: requestId,
191
+ zkProof: emptyBytes,
192
+ data: emptyBytes
193
+ });
194
+ continue;
195
+ }
182
196
  const zkProofEncoded = this.packZkpProof(inputs, zkProof.proof.pi_a.slice(0, 2), [
183
197
  [zkProof.proof.pi_b[0][1], zkProof.proof.pi_b[0][0]],
184
198
  [zkProof.proof.pi_b[1][1], zkProof.proof.pi_b[1][0]]
185
199
  ], zkProof.proof.pi_c.slice(0, 2));
186
- const stateInfo = this.getOnChainGistRootStatePubSignals(zkProof.circuitId, zkProof.pub_signals);
187
- const gistUpdateResolutions = [];
188
- for (const gist of stateInfo.gists) {
189
- const gistResolutionPending = gistUpdateResolutionsPending.find((g) => g == JSON.stringify(gist));
190
- if (gistResolutionPending) {
191
- continue;
192
- }
193
- gistUpdateResolutionsPending.push(JSON.stringify(gist));
194
- gistUpdateResolutions.push(this.resolveDidDocumentEip712MessageAndSignature(DID.parseFromId(gist.id), this._opts.didResolverUrl, { gist: gist.root }));
195
- }
196
- const stateUpdateResolutions = [];
197
- for (const state of stateInfo.states) {
198
- const stateResolutionPending = stateUpdateResolutionsPending.find((s) => s == JSON.stringify(state));
199
- if (stateResolutionPending) {
200
- continue;
201
- }
202
- stateUpdateResolutionsPending.push(JSON.stringify(state));
203
- stateUpdateResolutions.push(this.resolveDidDocumentEip712MessageAndSignature(DID.parseFromId(state.id), this._opts.didResolverUrl, {
204
- state: state.state
205
- }));
206
- }
200
+ const stateInfo = this.getOnChainGistRootStatePubSignals(proofCircuitId, inputs);
201
+ const chainId = txData.chain_id;
202
+ const gistUpdateResolutions = this.getCrossChainResolvers(stateInfo.gists, chainId, 'gist', resolverUrl);
203
+ const stateUpdateResolutions = this.getCrossChainResolvers(stateInfo.states, chainId, 'state', resolverUrl);
207
204
  if (gistUpdateResolutions.length > 0) {
208
- gistUpdateArr.push(...(await Promise.all(gistUpdateResolutions)));
205
+ gistUpdates.push(...(await Promise.all(gistUpdateResolutions)));
209
206
  }
210
207
  if (stateUpdateResolutions.length > 0) {
211
- stateUpdateArr.push(...(await Promise.all(stateUpdateResolutions)));
208
+ stateUpdates.push(...(await Promise.all(stateUpdateResolutions)));
212
209
  }
213
210
  const metadataArr = [];
214
211
  if (zkProof.vp) {
@@ -224,20 +221,28 @@ export class OnChainZKPVerifier {
224
221
  });
225
222
  }
226
223
  }
227
- const metadata = metadataArr.length ? this.packMetadatas(metadataArr) : '0x';
224
+ const metadata = metadataArr.length ? this.packMetadatas(metadataArr) : emptyBytes;
228
225
  payload.push({
229
- requestId: requestID,
226
+ requestId: requestId,
230
227
  zkProof: zkProofEncoded,
231
228
  data: metadata
232
229
  });
233
230
  }
234
- const crossChainProofs = this.packCrossChainProofs(gistUpdateArr, stateUpdateArr);
231
+ const crossChainProofs = gistUpdates.length || stateUpdates.length
232
+ ? this.packCrossChainProofs(gistUpdates, stateUpdates)
233
+ : emptyBytes;
235
234
  return [payload, crossChainProofs];
236
235
  }
237
- packZkpProof(inputs, a, b, c) {
238
- return this._abiCoder.encode(['uint256[] inputs', 'uint256[2]', 'uint256[2][2]', 'uint256[2]'], [inputs, a, b, c]);
236
+ async prepareTxArgsSubmitV2(txData, zkProofResponses) {
237
+ if (!this._opts?.didResolverUrl) {
238
+ throw new Error(`did resolver url required for crosschain verification`);
239
+ }
240
+ return OnChainZKPVerifier.prepareTxArgsSubmitV2(this._opts.didResolverUrl, txData, zkProofResponses);
239
241
  }
240
- packCrossChainProofs(gistUpdateArr, stateUpdateArr) {
242
+ static packZkpProof(inputs, a, b, c) {
243
+ return new ethers.AbiCoder().encode(['uint256[] inputs', 'uint256[2]', 'uint256[2][2]', 'uint256[2]'], [inputs, a, b, c]);
244
+ }
245
+ static packCrossChainProofs(gistUpdateArr, stateUpdateArr) {
241
246
  const proofs = [];
242
247
  for (const globalStateUpdate of gistUpdateArr) {
243
248
  proofs.push({
@@ -251,10 +256,10 @@ export class OnChainZKPVerifier {
251
256
  proof: this.packIdentityStateMsg(stateUpdate)
252
257
  });
253
258
  }
254
- return this._abiCoder.encode(['tuple(' + 'string proofType,' + 'bytes proof' + ')[]'], [proofs]);
259
+ return new ethers.AbiCoder().encode(['tuple(' + 'string proofType,' + 'bytes proof' + ')[]'], [proofs]);
255
260
  }
256
- packGlobalStateMsg(msg) {
257
- return this._abiCoder.encode([
261
+ static packGlobalStateMsg(msg) {
262
+ return new ethers.AbiCoder().encode([
258
263
  'tuple(' +
259
264
  'tuple(' +
260
265
  'uint256 timestamp,' +
@@ -266,8 +271,8 @@ export class OnChainZKPVerifier {
266
271
  ')'
267
272
  ], [msg]);
268
273
  }
269
- packIdentityStateMsg(msg) {
270
- return this._abiCoder.encode([
274
+ static packIdentityStateMsg(msg) {
275
+ return new ethers.AbiCoder().encode([
271
276
  'tuple(' +
272
277
  'tuple(' +
273
278
  'uint256 timestamp,' +
@@ -279,27 +284,20 @@ export class OnChainZKPVerifier {
279
284
  ')'
280
285
  ], [msg]);
281
286
  }
282
- packMetadatas(metas) {
283
- return this._abiCoder.encode(['tuple(' + 'string key,' + 'bytes value' + ')[]'], [metas]);
287
+ static packMetadatas(metas) {
288
+ return new ethers.AbiCoder().encode(['tuple(' + 'string key,' + 'bytes value' + ')[]'], [metas]);
284
289
  }
285
- getOnChainGistRootStatePubSignals(onChainCircuitId, inputs) {
286
- let atomicQueryPubSignals;
287
- switch (onChainCircuitId) {
288
- case CircuitId.AtomicQueryMTPV2OnChain:
289
- atomicQueryPubSignals = new AtomicQueryMTPV2OnChainPubSignals();
290
- break;
291
- case CircuitId.AtomicQuerySigV2OnChain:
292
- atomicQueryPubSignals = new AtomicQuerySigV2OnChainPubSignals();
293
- break;
294
- case CircuitId.AtomicQueryV3OnChain:
295
- atomicQueryPubSignals = new AtomicQueryV3OnChainPubSignals();
296
- break;
290
+ static getOnChainGistRootStatePubSignals(onChainCircuitId, inputs) {
291
+ const PubSignals = this._supportedCircuitsPubSignalsMap[onChainCircuitId];
292
+ if (!PubSignals) {
293
+ throw new Error(`Circuit ${onChainCircuitId} not supported by OnChainZKPVerifier`);
297
294
  }
295
+ const atomicQueryPubSignals = new PubSignals();
298
296
  const encodedInputs = byteEncoder.encode(JSON.stringify(inputs));
299
297
  atomicQueryPubSignals.pubSignalsUnmarshal(encodedInputs);
300
298
  return atomicQueryPubSignals.getStatesInfo();
301
299
  }
302
- async resolveDidDocumentEip712MessageAndSignature(did, resolverUrl, opts) {
300
+ static async resolveDidDocumentEip712MessageAndSignature(did, resolverUrl, opts) {
303
301
  const didDoc = await resolveDidDocument(did, resolverUrl, {
304
302
  ...opts,
305
303
  signature: DIDDocumentSignature.EthereumEip712Signature2021
@@ -332,3 +330,18 @@ export class OnChainZKPVerifier {
332
330
  };
333
331
  }
334
332
  }
333
+ /**
334
+ * supported circuits
335
+ */
336
+ OnChainZKPVerifier._supportedCircuits = [
337
+ CircuitId.AuthV2,
338
+ CircuitId.AtomicQueryMTPV2OnChain,
339
+ CircuitId.AtomicQuerySigV2OnChain,
340
+ CircuitId.AtomicQueryV3OnChain
341
+ ];
342
+ OnChainZKPVerifier._supportedCircuitsPubSignalsMap = {
343
+ [CircuitId.AtomicQueryMTPV2OnChain]: AtomicQueryMTPV2OnChainPubSignals,
344
+ [CircuitId.AtomicQuerySigV2OnChain]: AtomicQuerySigV2OnChainPubSignals,
345
+ [CircuitId.AtomicQueryV3OnChain]: AtomicQueryV3OnChainPubSignals,
346
+ [CircuitId.AuthV2]: AuthV2PubSignals
347
+ };
@@ -7,3 +7,4 @@ export * from './data-source';
7
7
  export * from './circuits';
8
8
  export * from './onchain-zkp-verifier';
9
9
  export * from './onchain-revocation';
10
+ export * from './onchain-issuer';
@@ -0,0 +1 @@
1
+ export {};
@@ -65,7 +65,7 @@ export const validateDIDDocumentAuth = async (did, resolverURL, state) => {
65
65
  }
66
66
  };
67
67
  export const resolveDIDDocumentAuth = async (did, resolveURL, state) => {
68
- let url = `${resolveURL}/${did.string().replace(/:/g, '%3A')}`;
68
+ let url = `${resolveURL}/${encodeURIComponent(did.string())}`;
69
69
  if (state) {
70
70
  url += `?state=${state.hex()}`;
71
71
  }
@@ -81,11 +81,11 @@ function emptyStateDID(did) {
81
81
  return emptyDID;
82
82
  }
83
83
  export const resolveDidDocument = async (did, resolverUrl, opts) => {
84
- let didString = did.string().replace(/:/g, '%3A');
84
+ let didString = encodeURIComponent(did.string());
85
85
  // for gist resolve we have to `hide` user did (look into resolver implementation)
86
86
  const isGistRequest = opts?.gist && !opts.state;
87
87
  if (isGistRequest) {
88
- didString = emptyStateDID(did).string();
88
+ didString = encodeURIComponent(emptyStateDID(did).string());
89
89
  }
90
90
  let url = `${resolverUrl}/1.0/identifiers/${didString}`;
91
91
  if (opts?.signature) {
@@ -97,9 +97,14 @@ export const resolveDidDocument = async (did, resolverUrl, opts) => {
97
97
  if (opts?.gist) {
98
98
  url += `${url.includes('?') ? '&' : '?'}gist=${opts.gist.hex()}`;
99
99
  }
100
- const resp = await fetch(url);
101
- const data = await resp.json();
102
- return data;
100
+ try {
101
+ const resp = await fetch(url);
102
+ const data = await resp.json();
103
+ return data;
104
+ }
105
+ catch (e) {
106
+ throw new Error(`Failed to resolve DID document for ${did} ${e}`);
107
+ }
103
108
  };
104
109
  export const buildDIDFromEthPubKey = (didType, pubKeyEth) => {
105
110
  // Use Keccak-256 hash function to get public key hash
@@ -146,6 +146,7 @@ export var SupportedPaymentProofType;
146
146
  /**
147
147
  * Media types for Payment supported currencies
148
148
  * @beta
149
+ * @deprecated
149
150
  * @enum {string}
150
151
  */
151
152
  export var SupportedCurrencies;
@@ -154,8 +155,7 @@ export var SupportedCurrencies;
154
155
  SupportedCurrencies["ETH_WEI"] = "ETHWEI";
155
156
  SupportedCurrencies["ETH_GWEI"] = "ETHGWEI";
156
157
  SupportedCurrencies["MATIC"] = "MATIC";
157
- SupportedCurrencies["USDT"] = "USDT";
158
- SupportedCurrencies["USDC"] = "USDC";
158
+ SupportedCurrencies["POL"] = "POL";
159
159
  })(SupportedCurrencies || (SupportedCurrencies = {}));
160
160
  /**
161
161
  * Supported features for payment-request