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