@0xpolygonid/js-sdk 1.10.0 → 1.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/esm/index.js +194 -11
- package/dist/browser/esm/index.js.map +1 -1
- package/dist/browser/umd/index.js +196 -10
- package/dist/browser/umd/index.js.map +1 -1
- package/dist/node/cjs/iden3comm/constants.js +5 -1
- package/dist/node/cjs/iden3comm/handlers/credential-proposal.js +213 -0
- package/dist/node/cjs/iden3comm/handlers/index.js +1 -0
- package/dist/node/cjs/iden3comm/types/index.js +1 -0
- package/dist/node/cjs/iden3comm/types/protocol/proposal-request.js +2 -0
- package/dist/node/cjs/proof/proof-service.js +2 -1
- package/dist/node/cjs/proof/verifiers/pub-signals-verifier.js +5 -6
- package/dist/node/cjs/storage/blockchain/state.js +2 -2
- package/dist/node/esm/iden3comm/constants.js +5 -1
- package/dist/node/esm/iden3comm/handlers/credential-proposal.js +184 -0
- package/dist/node/esm/iden3comm/handlers/index.js +1 -0
- package/dist/node/esm/iden3comm/types/index.js +1 -0
- package/dist/node/esm/iden3comm/types/protocol/proposal-request.js +1 -0
- package/dist/node/esm/proof/proof-service.js +2 -1
- package/dist/node/esm/proof/verifiers/pub-signals-verifier.js +5 -6
- package/dist/node/esm/storage/blockchain/state.js +2 -2
- package/dist/types/iden3comm/constants.d.ts +2 -0
- package/dist/types/iden3comm/handlers/credential-proposal.d.ts +112 -0
- package/dist/types/iden3comm/handlers/index.d.ts +1 -0
- package/dist/types/iden3comm/types/index.d.ts +1 -0
- package/dist/types/iden3comm/types/protocol/proposal-request.d.ts +35 -0
- package/dist/types/proof/proof-service.d.ts +1 -1
- package/dist/types/storage/blockchain/state.d.ts +1 -1
- package/dist/types/storage/interfaces/state.d.ts +5 -4
- package/package.json +1 -1
|
@@ -35,7 +35,11 @@ exports.PROTOCOL_MESSAGE_TYPE = Object.freeze({
|
|
|
35
35
|
// ContractInvokeRequestMessageType is type for request of contract invoke request
|
|
36
36
|
CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE: IDEN3_PROTOCOL + 'proofs/1.0/contract-invoke-request',
|
|
37
37
|
// CredentialOnchainOfferMessageType is type of message with credential onchain offering
|
|
38
|
-
CREDENTIAL_ONCHAIN_OFFER_MESSAGE_TYPE: IDEN3_PROTOCOL + 'credentials/1.0/onchain-offer'
|
|
38
|
+
CREDENTIAL_ONCHAIN_OFFER_MESSAGE_TYPE: IDEN3_PROTOCOL + 'credentials/1.0/onchain-offer',
|
|
39
|
+
// ProposalRequestMessageType is type for proposal-request message
|
|
40
|
+
PROPOSAL_REQUEST_MESSAGE_TYPE: IDEN3_PROTOCOL + 'credentials/0.1/proposal-request',
|
|
41
|
+
// ProposalMessageType is type for proposal message
|
|
42
|
+
PROPOSAL_MESSAGE_TYPE: IDEN3_PROTOCOL + 'credentials/0.1/proposal'
|
|
39
43
|
});
|
|
40
44
|
/**
|
|
41
45
|
* Media types for iden3 comm communication protocol
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.CredentialProposalHandler = exports.createProposal = exports.createProposalRequest = void 0;
|
|
27
|
+
const constants_1 = require("../constants");
|
|
28
|
+
const constants_2 = require("../constants");
|
|
29
|
+
const js_iden3_core_1 = require("@iden3/js-iden3-core");
|
|
30
|
+
const uuid = __importStar(require("uuid"));
|
|
31
|
+
const js_jwz_1 = require("@iden3/js-jwz");
|
|
32
|
+
const utils_1 = require("../../utils");
|
|
33
|
+
/**
|
|
34
|
+
* @beta
|
|
35
|
+
* createProposalRequest is a function to create protocol proposal-request protocol message
|
|
36
|
+
* @param {DID} sender - sender did
|
|
37
|
+
* @param {DID} receiver - receiver did
|
|
38
|
+
* @param {ProposalRequestCreationOptions} opts - creation options
|
|
39
|
+
* @returns `Promise<ProposalRequestMessage>`
|
|
40
|
+
*/
|
|
41
|
+
function createProposalRequest(sender, receiver, opts) {
|
|
42
|
+
const uuidv4 = uuid.v4();
|
|
43
|
+
const request = {
|
|
44
|
+
id: uuidv4,
|
|
45
|
+
thid: uuidv4,
|
|
46
|
+
from: sender.string(),
|
|
47
|
+
to: receiver.string(),
|
|
48
|
+
typ: constants_2.MediaType.PlainMessage,
|
|
49
|
+
type: constants_1.PROTOCOL_MESSAGE_TYPE.PROPOSAL_REQUEST_MESSAGE_TYPE,
|
|
50
|
+
body: opts
|
|
51
|
+
};
|
|
52
|
+
return request;
|
|
53
|
+
}
|
|
54
|
+
exports.createProposalRequest = createProposalRequest;
|
|
55
|
+
/**
|
|
56
|
+
* @beta
|
|
57
|
+
* createProposal is a function to create protocol proposal protocol message
|
|
58
|
+
* @param {DID} sender - sender did
|
|
59
|
+
* @param {DID} receiver - receiver did
|
|
60
|
+
* @param {Proposal[]} proposals - proposals
|
|
61
|
+
* @returns `Promise<ProposalRequestMessage>`
|
|
62
|
+
*/
|
|
63
|
+
function createProposal(sender, receiver, proposals) {
|
|
64
|
+
const uuidv4 = uuid.v4();
|
|
65
|
+
const request = {
|
|
66
|
+
id: uuidv4,
|
|
67
|
+
thid: uuidv4,
|
|
68
|
+
from: sender.string(),
|
|
69
|
+
to: receiver.string(),
|
|
70
|
+
typ: constants_2.MediaType.PlainMessage,
|
|
71
|
+
type: constants_1.PROTOCOL_MESSAGE_TYPE.PROPOSAL_MESSAGE_TYPE,
|
|
72
|
+
body: {
|
|
73
|
+
proposals: proposals || []
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
return request;
|
|
77
|
+
}
|
|
78
|
+
exports.createProposal = createProposal;
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
* Allows to process ProposalRequest protocol message
|
|
82
|
+
* @beta
|
|
83
|
+
* @class CredentialProposalHandler
|
|
84
|
+
* @implements implements ICredentialProposalHandler interface
|
|
85
|
+
*/
|
|
86
|
+
class CredentialProposalHandler {
|
|
87
|
+
/**
|
|
88
|
+
* @beta Creates an instance of CredentialProposalHandler.
|
|
89
|
+
* @param {IPackageManager} _packerMgr - package manager to unpack message envelope
|
|
90
|
+
* @param {IIdentityWallet} _identityWallet - identity wallet
|
|
91
|
+
* @param {CredentialProposalHandlerParams} _params - credential proposal handler params
|
|
92
|
+
*
|
|
93
|
+
*/
|
|
94
|
+
constructor(_packerMgr, _identityWallet, _params) {
|
|
95
|
+
this._packerMgr = _packerMgr;
|
|
96
|
+
this._identityWallet = _identityWallet;
|
|
97
|
+
this._params = _params;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* @inheritdoc ICredentialProposalHandler#parseProposalRequest
|
|
101
|
+
*/
|
|
102
|
+
async parseProposalRequest(request) {
|
|
103
|
+
const { unpackedMessage: message } = await this._packerMgr.unpack(request);
|
|
104
|
+
const proposalRequest = message;
|
|
105
|
+
if (message.type !== constants_1.PROTOCOL_MESSAGE_TYPE.PROPOSAL_REQUEST_MESSAGE_TYPE) {
|
|
106
|
+
throw new Error('Invalid media type');
|
|
107
|
+
}
|
|
108
|
+
return proposalRequest;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* @inheritdoc ICredentialProposalHandler#handleProposalRequest
|
|
112
|
+
*/
|
|
113
|
+
async handleProposalRequest(request,
|
|
114
|
+
//eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
115
|
+
opts) {
|
|
116
|
+
if (this._params.packerParams.mediaType === constants_2.MediaType.SignedMessage &&
|
|
117
|
+
!this._params.packerParams.packerOptions) {
|
|
118
|
+
throw new Error(`jws packer options are required for ${constants_2.MediaType.SignedMessage}`);
|
|
119
|
+
}
|
|
120
|
+
const proposalRequest = await this.parseProposalRequest(request);
|
|
121
|
+
if (!proposalRequest.to) {
|
|
122
|
+
throw new Error(`failed request. empty 'to' field`);
|
|
123
|
+
}
|
|
124
|
+
if (!proposalRequest.from) {
|
|
125
|
+
throw new Error(`failed request. empty 'from' field`);
|
|
126
|
+
}
|
|
127
|
+
if (!proposalRequest.body?.credentials?.length) {
|
|
128
|
+
throw new Error(`failed request. no 'credentials' in body`);
|
|
129
|
+
}
|
|
130
|
+
const senderDID = js_iden3_core_1.DID.parse(proposalRequest.from);
|
|
131
|
+
let credOfferMessage = undefined;
|
|
132
|
+
let proposalMessage = undefined;
|
|
133
|
+
for (let i = 0; i < proposalRequest.body.credentials.length; i++) {
|
|
134
|
+
const cred = proposalRequest.body.credentials[i];
|
|
135
|
+
// check if there is credentials in the wallet
|
|
136
|
+
let credsFromWallet = [];
|
|
137
|
+
try {
|
|
138
|
+
credsFromWallet = await this._identityWallet.findOwnedCredentialsByDID(senderDID, {
|
|
139
|
+
type: cred.type,
|
|
140
|
+
context: cred.context
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
if (e.message !== 'no credential satisfied query') {
|
|
145
|
+
throw e;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (credsFromWallet.length) {
|
|
149
|
+
const guid = uuid.v4();
|
|
150
|
+
if (!credOfferMessage) {
|
|
151
|
+
credOfferMessage = {
|
|
152
|
+
id: guid,
|
|
153
|
+
typ: this._params.packerParams.mediaType,
|
|
154
|
+
type: constants_1.PROTOCOL_MESSAGE_TYPE.CREDENTIAL_OFFER_MESSAGE_TYPE,
|
|
155
|
+
thid: proposalRequest.thid ?? guid,
|
|
156
|
+
body: {
|
|
157
|
+
url: this._params.agentUrl,
|
|
158
|
+
credentials: []
|
|
159
|
+
},
|
|
160
|
+
from: proposalRequest.to,
|
|
161
|
+
to: proposalRequest.from
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
credOfferMessage.body.credentials.push(...credsFromWallet.map((c) => ({
|
|
165
|
+
id: c.id,
|
|
166
|
+
description: ''
|
|
167
|
+
})));
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
// credential not found in the wallet, prepare proposal protocol message
|
|
171
|
+
const proposal = await this._params.proposalResolverFn(cred.context, cred.type);
|
|
172
|
+
if (!proposal) {
|
|
173
|
+
throw new Error(`can't resolve Proposal for type: ${cred.type}, context: ${cred.context}`);
|
|
174
|
+
}
|
|
175
|
+
if (!proposalMessage) {
|
|
176
|
+
const guid = uuid.v4();
|
|
177
|
+
proposalMessage = {
|
|
178
|
+
id: guid,
|
|
179
|
+
typ: this._params.packerParams.mediaType,
|
|
180
|
+
type: constants_1.PROTOCOL_MESSAGE_TYPE.PROPOSAL_MESSAGE_TYPE,
|
|
181
|
+
thid: proposalRequest.thid ?? guid,
|
|
182
|
+
body: {
|
|
183
|
+
proposals: []
|
|
184
|
+
},
|
|
185
|
+
from: proposalRequest.to,
|
|
186
|
+
to: proposalRequest.from
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
proposalMessage.body?.proposals.push(proposal);
|
|
190
|
+
}
|
|
191
|
+
// if there is credentials in the wallet, return offer protocol message, otherwise proposal
|
|
192
|
+
const response = utils_1.byteEncoder.encode(JSON.stringify(proposalMessage ?? credOfferMessage));
|
|
193
|
+
const packerOpts = this._params.packerParams.mediaType === constants_2.MediaType.SignedMessage
|
|
194
|
+
? this._params.packerParams.packerOptions
|
|
195
|
+
: {
|
|
196
|
+
provingMethodAlg: js_jwz_1.proving.provingMethodGroth16AuthV2Instance.methodAlg
|
|
197
|
+
};
|
|
198
|
+
return this._packerMgr.pack(this._params.packerParams.mediaType, response, {
|
|
199
|
+
senderDID,
|
|
200
|
+
...packerOpts
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* @inheritdoc ICredentialProposalHandler#handleProposal
|
|
205
|
+
*/
|
|
206
|
+
async handleProposal(proposal, opts) {
|
|
207
|
+
if (opts?.proposalRequest && opts.proposalRequest.from !== proposal.to) {
|
|
208
|
+
throw new Error(`sender of the request is not a target of response - expected ${opts.proposalRequest.from}, given ${proposal.to}`);
|
|
209
|
+
}
|
|
210
|
+
return { proposal };
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
exports.CredentialProposalHandler = CredentialProposalHandler;
|
|
@@ -20,5 +20,6 @@ __exportStar(require("./protocol/messages"), exports);
|
|
|
20
20
|
__exportStar(require("./protocol/proof"), exports);
|
|
21
21
|
__exportStar(require("./protocol/revocation"), exports);
|
|
22
22
|
__exportStar(require("./protocol/contract-request"), exports);
|
|
23
|
+
__exportStar(require("./protocol/proposal-request"), exports);
|
|
23
24
|
__exportStar(require("./packer"), exports);
|
|
24
25
|
__exportStar(require("./packageManager"), exports);
|
|
@@ -255,7 +255,8 @@ class ProofService {
|
|
|
255
255
|
throw new Error(`CircuitId is not supported ${circuitId}`);
|
|
256
256
|
}
|
|
257
257
|
const gistRoot = js_merkletree_1.Hash.fromString(pubSignals[2]).bigInt();
|
|
258
|
-
const
|
|
258
|
+
const userId = BigInt(pubSignals[0]);
|
|
259
|
+
const globalStateInfo = await this._stateStorage.getGISTRootInfo(gistRoot, userId);
|
|
259
260
|
if (globalStateInfo.createdAtTimestamp === 0n) {
|
|
260
261
|
throw new Error(`gist state doesn't exists in contract`);
|
|
261
262
|
}
|
|
@@ -220,7 +220,7 @@ class PubSignalsVerifier {
|
|
|
220
220
|
this.challenge = authV2PubSignals.challenge;
|
|
221
221
|
// no query verification
|
|
222
222
|
// verify state
|
|
223
|
-
const gist = await this.checkGlobalState(authV2PubSignals.GISTRoot);
|
|
223
|
+
const gist = await this.checkGlobalState(authV2PubSignals.GISTRoot, this.userId);
|
|
224
224
|
let acceptedStateTransitionDelay = defaultAuthVerifyOpts;
|
|
225
225
|
if (opts?.acceptedStateTransitionDelay) {
|
|
226
226
|
acceptedStateTransitionDelay = opts.acceptedStateTransitionDelay;
|
|
@@ -302,9 +302,8 @@ class PubSignalsVerifier {
|
|
|
302
302
|
throw exports.userStateError;
|
|
303
303
|
}
|
|
304
304
|
};
|
|
305
|
-
this.checkGlobalState = async (state) => {
|
|
306
|
-
|
|
307
|
-
return gistStateResolved;
|
|
305
|
+
this.checkGlobalState = async (state, id) => {
|
|
306
|
+
return this.rootResolve(state.bigInt(), id.bigInt());
|
|
308
307
|
};
|
|
309
308
|
this.checkRevocationStateForId = async (issuerId, issuerClaimNonRevState) => {
|
|
310
309
|
const issuerNonRevStateResolved = await this.resolve(issuerId, issuerClaimNonRevState.bigInt());
|
|
@@ -420,10 +419,10 @@ class PubSignalsVerifier {
|
|
|
420
419
|
}
|
|
421
420
|
return { latest: true, transitionTimestamp: 0 };
|
|
422
421
|
}
|
|
423
|
-
async rootResolve(state) {
|
|
422
|
+
async rootResolve(state, id) {
|
|
424
423
|
let globalStateInfo;
|
|
425
424
|
try {
|
|
426
|
-
globalStateInfo = await this._stateStorage.getGISTRootInfo(state);
|
|
425
|
+
globalStateInfo = await this._stateStorage.getGISTRootInfo(state, id);
|
|
427
426
|
}
|
|
428
427
|
catch (e) {
|
|
429
428
|
if (e.errorArgs[0] === 'Root does not exist') {
|
|
@@ -133,9 +133,9 @@ class EthStateStorage {
|
|
|
133
133
|
};
|
|
134
134
|
}
|
|
135
135
|
/** {@inheritdoc IStateStorage.getGISTRootInfo} */
|
|
136
|
-
async getGISTRootInfo(id) {
|
|
136
|
+
async getGISTRootInfo(root, id) {
|
|
137
137
|
const { stateContract } = this.getStateContractAndProviderForId(id);
|
|
138
|
-
const data = await stateContract.getGISTRootInfo(
|
|
138
|
+
const data = await stateContract.getGISTRootInfo(root);
|
|
139
139
|
return {
|
|
140
140
|
root: BigInt(data.root.toString()),
|
|
141
141
|
replacedByRoot: BigInt(data.replacedByRoot.toString()),
|
|
@@ -32,7 +32,11 @@ export const PROTOCOL_MESSAGE_TYPE = Object.freeze({
|
|
|
32
32
|
// ContractInvokeRequestMessageType is type for request of contract invoke request
|
|
33
33
|
CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE: IDEN3_PROTOCOL + 'proofs/1.0/contract-invoke-request',
|
|
34
34
|
// CredentialOnchainOfferMessageType is type of message with credential onchain offering
|
|
35
|
-
CREDENTIAL_ONCHAIN_OFFER_MESSAGE_TYPE: IDEN3_PROTOCOL + 'credentials/1.0/onchain-offer'
|
|
35
|
+
CREDENTIAL_ONCHAIN_OFFER_MESSAGE_TYPE: IDEN3_PROTOCOL + 'credentials/1.0/onchain-offer',
|
|
36
|
+
// ProposalRequestMessageType is type for proposal-request message
|
|
37
|
+
PROPOSAL_REQUEST_MESSAGE_TYPE: IDEN3_PROTOCOL + 'credentials/0.1/proposal-request',
|
|
38
|
+
// ProposalMessageType is type for proposal message
|
|
39
|
+
PROPOSAL_MESSAGE_TYPE: IDEN3_PROTOCOL + 'credentials/0.1/proposal'
|
|
36
40
|
});
|
|
37
41
|
/**
|
|
38
42
|
* Media types for iden3 comm communication protocol
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { PROTOCOL_MESSAGE_TYPE } from '../constants';
|
|
2
|
+
import { MediaType } from '../constants';
|
|
3
|
+
import { DID } from '@iden3/js-iden3-core';
|
|
4
|
+
import * as uuid from 'uuid';
|
|
5
|
+
import { proving } from '@iden3/js-jwz';
|
|
6
|
+
import { byteEncoder } from '../../utils';
|
|
7
|
+
/**
|
|
8
|
+
* @beta
|
|
9
|
+
* createProposalRequest is a function to create protocol proposal-request protocol message
|
|
10
|
+
* @param {DID} sender - sender did
|
|
11
|
+
* @param {DID} receiver - receiver did
|
|
12
|
+
* @param {ProposalRequestCreationOptions} opts - creation options
|
|
13
|
+
* @returns `Promise<ProposalRequestMessage>`
|
|
14
|
+
*/
|
|
15
|
+
export function createProposalRequest(sender, receiver, opts) {
|
|
16
|
+
const uuidv4 = uuid.v4();
|
|
17
|
+
const request = {
|
|
18
|
+
id: uuidv4,
|
|
19
|
+
thid: uuidv4,
|
|
20
|
+
from: sender.string(),
|
|
21
|
+
to: receiver.string(),
|
|
22
|
+
typ: MediaType.PlainMessage,
|
|
23
|
+
type: PROTOCOL_MESSAGE_TYPE.PROPOSAL_REQUEST_MESSAGE_TYPE,
|
|
24
|
+
body: opts
|
|
25
|
+
};
|
|
26
|
+
return request;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @beta
|
|
30
|
+
* createProposal is a function to create protocol proposal protocol message
|
|
31
|
+
* @param {DID} sender - sender did
|
|
32
|
+
* @param {DID} receiver - receiver did
|
|
33
|
+
* @param {Proposal[]} proposals - proposals
|
|
34
|
+
* @returns `Promise<ProposalRequestMessage>`
|
|
35
|
+
*/
|
|
36
|
+
export function createProposal(sender, receiver, proposals) {
|
|
37
|
+
const uuidv4 = uuid.v4();
|
|
38
|
+
const request = {
|
|
39
|
+
id: uuidv4,
|
|
40
|
+
thid: uuidv4,
|
|
41
|
+
from: sender.string(),
|
|
42
|
+
to: receiver.string(),
|
|
43
|
+
typ: MediaType.PlainMessage,
|
|
44
|
+
type: PROTOCOL_MESSAGE_TYPE.PROPOSAL_MESSAGE_TYPE,
|
|
45
|
+
body: {
|
|
46
|
+
proposals: proposals || []
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
return request;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* Allows to process ProposalRequest protocol message
|
|
54
|
+
* @beta
|
|
55
|
+
* @class CredentialProposalHandler
|
|
56
|
+
* @implements implements ICredentialProposalHandler interface
|
|
57
|
+
*/
|
|
58
|
+
export class CredentialProposalHandler {
|
|
59
|
+
/**
|
|
60
|
+
* @beta Creates an instance of CredentialProposalHandler.
|
|
61
|
+
* @param {IPackageManager} _packerMgr - package manager to unpack message envelope
|
|
62
|
+
* @param {IIdentityWallet} _identityWallet - identity wallet
|
|
63
|
+
* @param {CredentialProposalHandlerParams} _params - credential proposal handler params
|
|
64
|
+
*
|
|
65
|
+
*/
|
|
66
|
+
constructor(_packerMgr, _identityWallet, _params) {
|
|
67
|
+
this._packerMgr = _packerMgr;
|
|
68
|
+
this._identityWallet = _identityWallet;
|
|
69
|
+
this._params = _params;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* @inheritdoc ICredentialProposalHandler#parseProposalRequest
|
|
73
|
+
*/
|
|
74
|
+
async parseProposalRequest(request) {
|
|
75
|
+
const { unpackedMessage: message } = await this._packerMgr.unpack(request);
|
|
76
|
+
const proposalRequest = message;
|
|
77
|
+
if (message.type !== PROTOCOL_MESSAGE_TYPE.PROPOSAL_REQUEST_MESSAGE_TYPE) {
|
|
78
|
+
throw new Error('Invalid media type');
|
|
79
|
+
}
|
|
80
|
+
return proposalRequest;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* @inheritdoc ICredentialProposalHandler#handleProposalRequest
|
|
84
|
+
*/
|
|
85
|
+
async handleProposalRequest(request,
|
|
86
|
+
//eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
87
|
+
opts) {
|
|
88
|
+
if (this._params.packerParams.mediaType === MediaType.SignedMessage &&
|
|
89
|
+
!this._params.packerParams.packerOptions) {
|
|
90
|
+
throw new Error(`jws packer options are required for ${MediaType.SignedMessage}`);
|
|
91
|
+
}
|
|
92
|
+
const proposalRequest = await this.parseProposalRequest(request);
|
|
93
|
+
if (!proposalRequest.to) {
|
|
94
|
+
throw new Error(`failed request. empty 'to' field`);
|
|
95
|
+
}
|
|
96
|
+
if (!proposalRequest.from) {
|
|
97
|
+
throw new Error(`failed request. empty 'from' field`);
|
|
98
|
+
}
|
|
99
|
+
if (!proposalRequest.body?.credentials?.length) {
|
|
100
|
+
throw new Error(`failed request. no 'credentials' in body`);
|
|
101
|
+
}
|
|
102
|
+
const senderDID = DID.parse(proposalRequest.from);
|
|
103
|
+
let credOfferMessage = undefined;
|
|
104
|
+
let proposalMessage = undefined;
|
|
105
|
+
for (let i = 0; i < proposalRequest.body.credentials.length; i++) {
|
|
106
|
+
const cred = proposalRequest.body.credentials[i];
|
|
107
|
+
// check if there is credentials in the wallet
|
|
108
|
+
let credsFromWallet = [];
|
|
109
|
+
try {
|
|
110
|
+
credsFromWallet = await this._identityWallet.findOwnedCredentialsByDID(senderDID, {
|
|
111
|
+
type: cred.type,
|
|
112
|
+
context: cred.context
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
if (e.message !== 'no credential satisfied query') {
|
|
117
|
+
throw e;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (credsFromWallet.length) {
|
|
121
|
+
const guid = uuid.v4();
|
|
122
|
+
if (!credOfferMessage) {
|
|
123
|
+
credOfferMessage = {
|
|
124
|
+
id: guid,
|
|
125
|
+
typ: this._params.packerParams.mediaType,
|
|
126
|
+
type: PROTOCOL_MESSAGE_TYPE.CREDENTIAL_OFFER_MESSAGE_TYPE,
|
|
127
|
+
thid: proposalRequest.thid ?? guid,
|
|
128
|
+
body: {
|
|
129
|
+
url: this._params.agentUrl,
|
|
130
|
+
credentials: []
|
|
131
|
+
},
|
|
132
|
+
from: proposalRequest.to,
|
|
133
|
+
to: proposalRequest.from
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
credOfferMessage.body.credentials.push(...credsFromWallet.map((c) => ({
|
|
137
|
+
id: c.id,
|
|
138
|
+
description: ''
|
|
139
|
+
})));
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
// credential not found in the wallet, prepare proposal protocol message
|
|
143
|
+
const proposal = await this._params.proposalResolverFn(cred.context, cred.type);
|
|
144
|
+
if (!proposal) {
|
|
145
|
+
throw new Error(`can't resolve Proposal for type: ${cred.type}, context: ${cred.context}`);
|
|
146
|
+
}
|
|
147
|
+
if (!proposalMessage) {
|
|
148
|
+
const guid = uuid.v4();
|
|
149
|
+
proposalMessage = {
|
|
150
|
+
id: guid,
|
|
151
|
+
typ: this._params.packerParams.mediaType,
|
|
152
|
+
type: PROTOCOL_MESSAGE_TYPE.PROPOSAL_MESSAGE_TYPE,
|
|
153
|
+
thid: proposalRequest.thid ?? guid,
|
|
154
|
+
body: {
|
|
155
|
+
proposals: []
|
|
156
|
+
},
|
|
157
|
+
from: proposalRequest.to,
|
|
158
|
+
to: proposalRequest.from
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
proposalMessage.body?.proposals.push(proposal);
|
|
162
|
+
}
|
|
163
|
+
// if there is credentials in the wallet, return offer protocol message, otherwise proposal
|
|
164
|
+
const response = byteEncoder.encode(JSON.stringify(proposalMessage ?? credOfferMessage));
|
|
165
|
+
const packerOpts = this._params.packerParams.mediaType === MediaType.SignedMessage
|
|
166
|
+
? this._params.packerParams.packerOptions
|
|
167
|
+
: {
|
|
168
|
+
provingMethodAlg: proving.provingMethodGroth16AuthV2Instance.methodAlg
|
|
169
|
+
};
|
|
170
|
+
return this._packerMgr.pack(this._params.packerParams.mediaType, response, {
|
|
171
|
+
senderDID,
|
|
172
|
+
...packerOpts
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* @inheritdoc ICredentialProposalHandler#handleProposal
|
|
177
|
+
*/
|
|
178
|
+
async handleProposal(proposal, opts) {
|
|
179
|
+
if (opts?.proposalRequest && opts.proposalRequest.from !== proposal.to) {
|
|
180
|
+
throw new Error(`sender of the request is not a target of response - expected ${opts.proposalRequest.from}, given ${proposal.to}`);
|
|
181
|
+
}
|
|
182
|
+
return { proposal };
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -252,7 +252,8 @@ export class ProofService {
|
|
|
252
252
|
throw new Error(`CircuitId is not supported ${circuitId}`);
|
|
253
253
|
}
|
|
254
254
|
const gistRoot = Hash.fromString(pubSignals[2]).bigInt();
|
|
255
|
-
const
|
|
255
|
+
const userId = BigInt(pubSignals[0]);
|
|
256
|
+
const globalStateInfo = await this._stateStorage.getGISTRootInfo(gistRoot, userId);
|
|
256
257
|
if (globalStateInfo.createdAtTimestamp === 0n) {
|
|
257
258
|
throw new Error(`gist state doesn't exists in contract`);
|
|
258
259
|
}
|
|
@@ -217,7 +217,7 @@ export class PubSignalsVerifier {
|
|
|
217
217
|
this.challenge = authV2PubSignals.challenge;
|
|
218
218
|
// no query verification
|
|
219
219
|
// verify state
|
|
220
|
-
const gist = await this.checkGlobalState(authV2PubSignals.GISTRoot);
|
|
220
|
+
const gist = await this.checkGlobalState(authV2PubSignals.GISTRoot, this.userId);
|
|
221
221
|
let acceptedStateTransitionDelay = defaultAuthVerifyOpts;
|
|
222
222
|
if (opts?.acceptedStateTransitionDelay) {
|
|
223
223
|
acceptedStateTransitionDelay = opts.acceptedStateTransitionDelay;
|
|
@@ -299,9 +299,8 @@ export class PubSignalsVerifier {
|
|
|
299
299
|
throw userStateError;
|
|
300
300
|
}
|
|
301
301
|
};
|
|
302
|
-
this.checkGlobalState = async (state) => {
|
|
303
|
-
|
|
304
|
-
return gistStateResolved;
|
|
302
|
+
this.checkGlobalState = async (state, id) => {
|
|
303
|
+
return this.rootResolve(state.bigInt(), id.bigInt());
|
|
305
304
|
};
|
|
306
305
|
this.checkRevocationStateForId = async (issuerId, issuerClaimNonRevState) => {
|
|
307
306
|
const issuerNonRevStateResolved = await this.resolve(issuerId, issuerClaimNonRevState.bigInt());
|
|
@@ -417,10 +416,10 @@ export class PubSignalsVerifier {
|
|
|
417
416
|
}
|
|
418
417
|
return { latest: true, transitionTimestamp: 0 };
|
|
419
418
|
}
|
|
420
|
-
async rootResolve(state) {
|
|
419
|
+
async rootResolve(state, id) {
|
|
421
420
|
let globalStateInfo;
|
|
422
421
|
try {
|
|
423
|
-
globalStateInfo = await this._stateStorage.getGISTRootInfo(state);
|
|
422
|
+
globalStateInfo = await this._stateStorage.getGISTRootInfo(state, id);
|
|
424
423
|
}
|
|
425
424
|
catch (e) {
|
|
426
425
|
if (e.errorArgs[0] === 'Root does not exist') {
|
|
@@ -127,9 +127,9 @@ export class EthStateStorage {
|
|
|
127
127
|
};
|
|
128
128
|
}
|
|
129
129
|
/** {@inheritdoc IStateStorage.getGISTRootInfo} */
|
|
130
|
-
async getGISTRootInfo(id) {
|
|
130
|
+
async getGISTRootInfo(root, id) {
|
|
131
131
|
const { stateContract } = this.getStateContractAndProviderForId(id);
|
|
132
|
-
const data = await stateContract.getGISTRootInfo(
|
|
132
|
+
const data = await stateContract.getGISTRootInfo(root);
|
|
133
133
|
return {
|
|
134
134
|
root: BigInt(data.root.toString()),
|
|
135
135
|
replacedByRoot: BigInt(data.replacedByRoot.toString()),
|
|
@@ -17,6 +17,8 @@ export declare const PROTOCOL_MESSAGE_TYPE: Readonly<{
|
|
|
17
17
|
REVOCATION_STATUS_RESPONSE_MESSAGE_TYPE: string;
|
|
18
18
|
CONTRACT_INVOKE_REQUEST_MESSAGE_TYPE: string;
|
|
19
19
|
CREDENTIAL_ONCHAIN_OFFER_MESSAGE_TYPE: string;
|
|
20
|
+
PROPOSAL_REQUEST_MESSAGE_TYPE: string;
|
|
21
|
+
PROPOSAL_MESSAGE_TYPE: string;
|
|
20
22
|
}>;
|
|
21
23
|
/**
|
|
22
24
|
* Media types for iden3 comm communication protocol
|