@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
@@ -51,6 +51,92 @@ class W3CCredential {
51
51
  this.credentialSubject = {};
52
52
  this.issuer = '';
53
53
  }
54
+ /**
55
+ *
56
+ * @param issuer - DID of the issuer
57
+ * @param request - Credential request
58
+ * @returns - W3C Credential
59
+ */
60
+ static fromCredentialRequest(issuer, request) {
61
+ if (!request.id) {
62
+ throw new Error('Credential id is required');
63
+ }
64
+ if (!request.context) {
65
+ throw new Error('Credential context is required');
66
+ }
67
+ const context = [
68
+ constants_1.VerifiableConstants.JSONLD_SCHEMA.W3C_CREDENTIAL_2018,
69
+ constants_1.VerifiableConstants.JSONLD_SCHEMA.IDEN3_CREDENTIAL,
70
+ ...request.context
71
+ ];
72
+ const credentialType = [
73
+ constants_1.VerifiableConstants.CREDENTIAL_TYPE.W3C_VERIFIABLE_CREDENTIAL,
74
+ request.type
75
+ ];
76
+ const credentialSubject = request.credentialSubject;
77
+ credentialSubject['type'] = request.type;
78
+ const cr = new W3CCredential();
79
+ cr.id = request.id;
80
+ cr['@context'] = context;
81
+ cr.type = credentialType;
82
+ cr.credentialSubject = credentialSubject;
83
+ cr.issuer = issuer.string();
84
+ cr.credentialSchema = {
85
+ id: request.credentialSchema,
86
+ type: constants_1.VerifiableConstants.JSON_SCHEMA_VALIDATOR
87
+ };
88
+ cr.credentialStatus = W3CCredential.buildCredentialStatus(request, issuer);
89
+ request.expiration && (cr.expirationDate = new Date(request.expiration).toISOString());
90
+ request.refreshService && (cr.refreshService = request.refreshService);
91
+ request.displayMethod && (cr.displayMethod = request.displayMethod);
92
+ request.issuanceDate && (cr.issuanceDate = new Date(request.issuanceDate).toISOString());
93
+ return cr;
94
+ }
95
+ /**
96
+ * Builds credential status
97
+ * @param {CredentialRequest} request
98
+ * @returns `CredentialStatus`
99
+ */
100
+ static buildCredentialStatus(request, issuer) {
101
+ const credentialStatus = {
102
+ id: request.revocationOpts.id,
103
+ type: request.revocationOpts.type,
104
+ revocationNonce: request.revocationOpts.nonce
105
+ };
106
+ switch (request.revocationOpts.type) {
107
+ case constants_1.CredentialStatusType.SparseMerkleTreeProof:
108
+ return {
109
+ ...credentialStatus,
110
+ id: `${credentialStatus.id.replace(/\/$/, '')}/${credentialStatus.revocationNonce}`
111
+ };
112
+ case constants_1.CredentialStatusType.Iden3ReverseSparseMerkleTreeProof:
113
+ return {
114
+ ...credentialStatus,
115
+ id: request.revocationOpts.issuerState
116
+ ? `${credentialStatus.id.replace(/\/$/, '')}/node?state=${request.revocationOpts.issuerState}`
117
+ : `${credentialStatus.id.replace(/\/$/, '')}`
118
+ };
119
+ case constants_1.CredentialStatusType.Iden3OnchainSparseMerkleTreeProof2023: {
120
+ const issuerId = js_iden3_core_1.DID.idFromDID(issuer);
121
+ const chainId = (0, js_iden3_core_1.getChainId)(js_iden3_core_1.DID.blockchainFromId(issuerId), js_iden3_core_1.DID.networkIdFromId(issuerId));
122
+ const searchParams = [
123
+ ['revocationNonce', request.revocationOpts.nonce?.toString() || ''],
124
+ ['contractAddress', `${chainId}:${request.revocationOpts.id}`],
125
+ ['state', request.revocationOpts.issuerState || '']
126
+ ]
127
+ .filter(([, value]) => Boolean(value))
128
+ .map(([key, value]) => `${key}=${value}`)
129
+ .join('&');
130
+ return {
131
+ ...credentialStatus,
132
+ // `[did]:[methodid]:[chain]:[network]:[id]/credentialStatus?(revocationNonce=value)&[contractAddress=[chainID]:[contractAddress]]&(state=issuerState)`
133
+ id: `${issuer.string()}/credentialStatus?${searchParams}`
134
+ };
135
+ }
136
+ default:
137
+ return credentialStatus;
138
+ }
139
+ }
54
140
  toJSON() {
55
141
  return {
56
142
  ...this,
@@ -88,4 +88,10 @@ export class AuthV2PubSignals {
88
88
  this.GISTRoot = Hash.fromString(sVals[2]);
89
89
  return this;
90
90
  }
91
+ getStatesInfo() {
92
+ return {
93
+ states: [],
94
+ gists: [{ id: this.userID, root: this.GISTRoot }]
95
+ };
96
+ }
91
97
  }
@@ -1,4 +1,4 @@
1
- import { DID, getChainId } from '@iden3/js-iden3-core';
1
+ import { DID } from '@iden3/js-iden3-core';
2
2
  import { W3CCredential, VerifiableConstants, CredentialStatusType, DisplayMethodType } from './../verifiable';
3
3
  import * as uuid from 'uuid';
4
4
  import { CredentialStatusResolverRegistry } from './status/resolver';
@@ -31,40 +31,18 @@ export class CredentialWallet {
31
31
  if (!schema.$metadata.uris['jsonLdContext']) {
32
32
  throw new Error('jsonLdContext is missing is the schema');
33
33
  }
34
- request.context = request.context ?? [];
35
- if (request.displayMethod?.type === DisplayMethodType.Iden3BasicDisplayMethodV1 &&
36
- !request.context.includes(VerifiableConstants.JSONLD_SCHEMA.IDEN3_DISPLAY_METHOD)) {
37
- request.context.push(VerifiableConstants.JSONLD_SCHEMA.IDEN3_DISPLAY_METHOD);
34
+ // do copy of request to avoid mutation
35
+ const r = { ...request };
36
+ r.context = r.context ?? [];
37
+ if (r.displayMethod?.type === DisplayMethodType.Iden3BasicDisplayMethodV1 &&
38
+ !r.context.includes(VerifiableConstants.JSONLD_SCHEMA.IDEN3_DISPLAY_METHOD)) {
39
+ r.context.push(VerifiableConstants.JSONLD_SCHEMA.IDEN3_DISPLAY_METHOD);
38
40
  }
39
- const context = [
40
- VerifiableConstants.JSONLD_SCHEMA.W3C_CREDENTIAL_2018,
41
- ...request.context,
42
- VerifiableConstants.JSONLD_SCHEMA.IDEN3_CREDENTIAL,
43
- schema.$metadata.uris['jsonLdContext']
44
- ];
45
- const credentialType = [
46
- VerifiableConstants.CREDENTIAL_TYPE.W3C_VERIFIABLE_CREDENTIAL,
47
- request.type
48
- ];
49
- const expirationDate = !request.expiration || request.expiration == 0 ? null : request.expiration;
50
- const credentialSubject = request.credentialSubject;
51
- credentialSubject['type'] = request.type;
52
- const cr = new W3CCredential();
53
- cr.id = `urn:${uuid.v4()}`;
54
- cr['@context'] = context;
55
- cr.type = credentialType;
56
- cr.expirationDate = expirationDate ? new Date(expirationDate * 1000).toISOString() : undefined;
57
- cr.refreshService = request.refreshService;
58
- cr.displayMethod = request.displayMethod;
59
- cr.issuanceDate = new Date().toISOString();
60
- cr.credentialSubject = credentialSubject;
61
- cr.issuer = issuer.string();
62
- cr.credentialSchema = {
63
- id: request.credentialSchema,
64
- type: VerifiableConstants.JSON_SCHEMA_VALIDATOR
65
- };
66
- cr.credentialStatus = this.buildCredentialStatus(request, issuer);
67
- return cr;
41
+ r.context.push(schema.$metadata.uris['jsonLdContext']);
42
+ r.expiration = r.expiration ? r.expiration * 1000 : undefined;
43
+ r.id = r.id ? r.id : `urn:${uuid.v4()}`;
44
+ r.issuanceDate = r.issuanceDate ? r.issuanceDate * 1000 : Date.now();
45
+ return W3CCredential.fromCredentialRequest(issuer, r);
68
46
  };
69
47
  // if no credential status resolvers are provided
70
48
  // register default issuer resolver
@@ -134,51 +112,6 @@ export class CredentialWallet {
134
112
  }
135
113
  return statusResolver.resolve(credStatus, credentialStatusResolveOptions);
136
114
  }
137
- /**
138
- * Builds credential status
139
- * @param {CredentialRequest} request
140
- * @returns `CredentialStatus`
141
- */
142
- buildCredentialStatus(request, issuer) {
143
- const credentialStatus = {
144
- id: request.revocationOpts.id,
145
- type: request.revocationOpts.type,
146
- revocationNonce: request.revocationOpts.nonce
147
- };
148
- switch (request.revocationOpts.type) {
149
- case CredentialStatusType.SparseMerkleTreeProof:
150
- return {
151
- ...credentialStatus,
152
- id: `${credentialStatus.id.replace(/\/$/, '')}/${credentialStatus.revocationNonce}`
153
- };
154
- case CredentialStatusType.Iden3ReverseSparseMerkleTreeProof:
155
- return {
156
- ...credentialStatus,
157
- id: request.revocationOpts.issuerState
158
- ? `${credentialStatus.id.replace(/\/$/, '')}/node?state=${request.revocationOpts.issuerState}`
159
- : `${credentialStatus.id.replace(/\/$/, '')}`
160
- };
161
- case CredentialStatusType.Iden3OnchainSparseMerkleTreeProof2023: {
162
- const issuerId = DID.idFromDID(issuer);
163
- const chainId = getChainId(DID.blockchainFromId(issuerId), DID.networkIdFromId(issuerId));
164
- const searchParams = [
165
- ['revocationNonce', request.revocationOpts.nonce?.toString() || ''],
166
- ['contractAddress', `${chainId}:${request.revocationOpts.id}`],
167
- ['state', request.revocationOpts.issuerState || '']
168
- ]
169
- .filter(([, value]) => Boolean(value))
170
- .map(([key, value]) => `${key}=${value}`)
171
- .join('&');
172
- return {
173
- ...credentialStatus,
174
- // `[did]:[methodid]:[chain]:[network]:[id]/credentialStatus?(revocationNonce=value)&[contractAddress=[chainID]:[contractAddress]]&(state=issuerState)`
175
- id: `${issuer.string()}/credentialStatus?${searchParams}`
176
- };
177
- }
178
- default:
179
- return credentialStatus;
180
- }
181
- }
182
115
  /**
183
116
  * {@inheritDoc ICredentialWallet.findById}
184
117
  */
@@ -4,6 +4,7 @@ export * from './status/sparse-merkle-tree';
4
4
  export * from './status/resolver';
5
5
  export * from './status/agent-revocation';
6
6
  export * from './status/credential-status-publisher';
7
+ export * from './status/did-resolver-revocation';
7
8
  export * from './credential-wallet';
8
9
  export * from './rhs';
9
10
  export * from './utils';
@@ -0,0 +1,17 @@
1
+ export class DidDocumentCredentialStatusResolver {
2
+ constructor(didResolverUrl) {
3
+ this.didResolverUrl = didResolverUrl;
4
+ }
5
+ async resolve(credentialStatus, opts) {
6
+ if (!opts?.issuerDID) {
7
+ throw new Error('IssuerDID is not set in options');
8
+ }
9
+ const url = `${this.didResolverUrl}/1.0/credential-status/${encodeURIComponent(opts.issuerDID.string())}`;
10
+ const resp = await fetch(url, {
11
+ method: 'POST',
12
+ body: JSON.stringify(credentialStatus)
13
+ });
14
+ const data = await resp.json();
15
+ return data;
16
+ }
17
+ }
@@ -27,6 +27,7 @@ export class ContractRequestHandler extends AbstractMessageHandler {
27
27
  this._proofService = _proofService;
28
28
  this._zkpVerifier = _zkpVerifier;
29
29
  this._supportedCircuits = [
30
+ CircuitId.AuthV2,
30
31
  CircuitId.AtomicQueryMTPV2OnChain,
31
32
  CircuitId.AtomicQuerySigV2OnChain,
32
33
  CircuitId.AtomicQueryV3OnChain
@@ -57,7 +58,12 @@ export class ContractRequestHandler extends AbstractMessageHandler {
57
58
  throw new Error(`Invalid chain id ${chain_id}`);
58
59
  }
59
60
  const verifierDid = message.from ? DID.parse(message.from) : undefined;
60
- const zkpResponses = await processZeroKnowledgeProofRequests(did, message?.body?.scope, verifierDid, this._proofService, { ethSigner, challenge, supportedCircuits: this._supportedCircuits });
61
+ const { scope = [] } = message.body;
62
+ const zkpResponses = await processZeroKnowledgeProofRequests(did, scope, verifierDid, this._proofService, {
63
+ ethSigner,
64
+ challenge,
65
+ supportedCircuits: this._supportedCircuits
66
+ });
61
67
  const methodId = message.body.transaction_data.method_id.replace('0x', '');
62
68
  switch (methodId) {
63
69
  case FunctionSignatures.SubmitZKPResponseV2:
@@ -47,10 +47,34 @@ export class FetchHandler extends AbstractMessageHandler {
47
47
  return this.handleFetchRequest(message);
48
48
  case PROTOCOL_MESSAGE_TYPE.CREDENTIAL_ISSUANCE_RESPONSE_MESSAGE_TYPE:
49
49
  return this.handleIssuanceResponseMsg(message);
50
+ case PROTOCOL_MESSAGE_TYPE.CREDENTIAL_ONCHAIN_OFFER_MESSAGE_TYPE: {
51
+ const result = await this.handleOnchainOfferMessage(message);
52
+ if (Array.isArray(result)) {
53
+ const credWallet = this.opts?.credentialWallet;
54
+ if (!credWallet)
55
+ throw new Error('Credential wallet is not provided');
56
+ await credWallet.saveAll(result);
57
+ return null;
58
+ }
59
+ return result;
60
+ }
50
61
  default:
51
62
  return super.handle(message, ctx);
52
63
  }
53
64
  }
65
+ async handleOnchainOfferMessage(offerMessage) {
66
+ if (!this.opts?.onchainIssuer) {
67
+ throw new Error('onchain issuer is not provided');
68
+ }
69
+ const credentials = [];
70
+ for (const credentialInfo of offerMessage.body.credentials) {
71
+ const issuerDID = DID.parse(offerMessage.from);
72
+ const userDID = DID.parse(offerMessage.to);
73
+ const credential = await this.opts.onchainIssuer.getCredential(issuerDID, userDID, BigInt(credentialInfo.id));
74
+ credentials.push(credential);
75
+ }
76
+ return credentials;
77
+ }
54
78
  async handleOfferMessage(offerMessage, ctx) {
55
79
  if (!ctx.mediaType) {
56
80
  ctx.mediaType = MediaType.ZKPMessage;
@@ -135,6 +159,14 @@ export class FetchHandler extends AbstractMessageHandler {
135
159
  }
136
160
  throw new Error('invalid protocol message response');
137
161
  }
162
+ /**
163
+ * Handles only messages with credentials/1.0/onchain-offer type
164
+ * @beta
165
+ */
166
+ async handleOnchainOffer(offer) {
167
+ const offerMessage = await FetchHandler.unpackMessage(this._packerMgr, offer, PROTOCOL_MESSAGE_TYPE.CREDENTIAL_ONCHAIN_OFFER_MESSAGE_TYPE);
168
+ return this.handleOnchainOfferMessage(offerMessage);
169
+ }
138
170
  async handleFetchRequest(msgRequest) {
139
171
  if (!msgRequest.to) {
140
172
  throw new Error("failed request. empty 'to' field");
@@ -40,7 +40,7 @@ export async function verifyEIP712TypedData(data, resolver) {
40
40
  ? {
41
41
  recipient: data.recipient,
42
42
  amount: data.amount,
43
- expirationDate: new Date(data.expirationDate).getTime(),
43
+ expirationDate: getUnixTimestamp(new Date(data.expirationDate)),
44
44
  nonce: data.nonce,
45
45
  metadata: '0x'
46
46
  }
@@ -48,7 +48,7 @@ export async function verifyEIP712TypedData(data, resolver) {
48
48
  tokenAddress: data.tokenAddress,
49
49
  recipient: data.recipient,
50
50
  amount: data.amount,
51
- expirationDate: new Date(data.expirationDate).getTime(),
51
+ expirationDate: getUnixTimestamp(new Date(data.expirationDate)),
52
52
  nonce: data.nonce,
53
53
  metadata: '0x'
54
54
  };
@@ -257,37 +257,39 @@ export class PaymentHandler extends AbstractMessageHandler {
257
257
  for (let i = 0; i < payments.length; i++) {
258
258
  const { credentials, description } = payments[i];
259
259
  const dataArr = [];
260
- for (let j = 0; j < payments[i].chains.length; j++) {
261
- const { features, nonce, amount, currency, chainId, expirationDate, type } = payments[i].chains[j];
260
+ for (let j = 0; j < payments[i].options.length; j++) {
261
+ const { nonce, amount, chainId, optionId, expirationDate } = payments[i].options[j];
262
262
  const multiChainConfig = this._params.multiChainPaymentConfig?.find((c) => c.chainId === chainId);
263
263
  if (!multiChainConfig) {
264
264
  throw new Error(`failed request. no config for chain ${chainId}`);
265
265
  }
266
- const { recipient, paymentContract, erc20TokenAddressArr } = multiChainConfig;
267
- const tokenAddress = erc20TokenAddressArr.find((t) => t.symbol === currency)?.address;
268
- if (type === PaymentRequestDataType.Iden3PaymentRailsERC20RequestV1 && !tokenAddress) {
269
- throw new Error(`failed request. no token address for currency ${currency}`);
266
+ const { recipient, paymentRails, options } = multiChainConfig;
267
+ const option = options.find((t) => t.id === optionId);
268
+ if (!option) {
269
+ throw new Error(`failed request. no option for id ${optionId}`);
270
270
  }
271
- const expirationTime = expirationDate
272
- ? new Date(expirationDate).getTime()
273
- : new Date(new Date().setHours(new Date().getHours() + 1)).getTime();
274
- const typeUrl = `https://schema.iden3.io/core/json/${type}.json`;
271
+ if (option.type === PaymentRequestDataType.Iden3PaymentRailsERC20RequestV1 &&
272
+ !option.contractAddress) {
273
+ throw new Error(`failed request. no token address for option id ${optionId}`);
274
+ }
275
+ const expirationDateRequired = expirationDate ?? new Date(new Date().setHours(new Date().getHours() + 1));
276
+ const typeUrl = `https://schema.iden3.io/core/json/${option.type}.json`;
275
277
  const typesFetchResult = await fetch(typeUrl);
276
278
  const types = await typesFetchResult.json();
277
279
  delete types.EIP712Domain;
278
- const paymentData = type === PaymentRequestDataType.Iden3PaymentRailsRequestV1
280
+ const paymentData = option.type === PaymentRequestDataType.Iden3PaymentRailsRequestV1
279
281
  ? {
280
282
  recipient,
281
- amount,
282
- expirationDate: expirationTime,
283
+ amount: amount,
284
+ expirationDate: getUnixTimestamp(expirationDateRequired),
283
285
  nonce,
284
286
  metadata: '0x'
285
287
  }
286
288
  : {
287
- tokenAddress,
289
+ tokenAddress: option.contractAddress,
288
290
  recipient,
289
- amount,
290
- expirationDate: expirationTime,
291
+ amount: amount,
292
+ expirationDate: getUnixTimestamp(expirationDateRequired),
291
293
  nonce,
292
294
  metadata: '0x'
293
295
  };
@@ -295,7 +297,7 @@ export class PaymentHandler extends AbstractMessageHandler {
295
297
  name: 'MCPayment',
296
298
  version: '1.0.0',
297
299
  chainId,
298
- verifyingContract: paymentContract
300
+ verifyingContract: paymentRails
299
301
  };
300
302
  const signature = await signer.signTypedData(domain, types, paymentData);
301
303
  const proof = [
@@ -315,20 +317,24 @@ export class PaymentHandler extends AbstractMessageHandler {
315
317
  const d = {
316
318
  type: PaymentRequestDataType.Iden3PaymentRailsRequestV1,
317
319
  '@context': [
318
- `https://schema.iden3.io/core/jsonld/payment.jsonld#${type}`,
320
+ `https://schema.iden3.io/core/jsonld/payment.jsonld#${option.type}`,
319
321
  'https://w3id.org/security/suites/eip712sig-2021/v1'
320
322
  ],
321
323
  recipient,
322
324
  amount: amount.toString(),
323
- currency,
324
- expirationDate: new Date(expirationTime).toISOString(),
325
+ expirationDate: expirationDateRequired.toISOString(),
325
326
  nonce: nonce.toString(),
326
327
  metadata: '0x',
327
328
  proof
328
329
  };
329
- dataArr.push(type === PaymentRequestDataType.Iden3PaymentRailsRequestV1
330
+ dataArr.push(option.type === PaymentRequestDataType.Iden3PaymentRailsRequestV1
330
331
  ? d
331
- : { ...d, type, tokenAddress: tokenAddress || '', features: features || [] });
332
+ : {
333
+ ...d,
334
+ type: option.type,
335
+ tokenAddress: option.contractAddress || '',
336
+ features: option.features || []
337
+ });
332
338
  }
333
339
  paymentRequestInfo.push({
334
340
  data: dataArr,
@@ -0,0 +1,54 @@
1
+ import { keccak256 } from 'ethers';
2
+ import { byteEncoder, hexToBytes, isEthereumIdentity } from '../../utils';
3
+ import { CircuitId } from '../../circuits';
4
+ import { Hex } from '@iden3/js-crypto';
5
+ /**
6
+ * @beta
7
+ * Retrieves the request ID from circuit string.
8
+ * CircuitId.AuthV2 - 940499666
9
+ * @returns The request ID.
10
+ */
11
+ export function calculateRequestIdForCircuit(circuitId) {
12
+ const circuitHash = keccak256(byteEncoder.encode(circuitId));
13
+ const dataView = new DataView(Hex.decodeString(circuitHash.replace('0x', '')).buffer);
14
+ const id = dataView.getUint32(0);
15
+ return id;
16
+ }
17
+ /**
18
+ * Prepares the zero-knowledge proof response for the AuthV2 circuit.
19
+ * @beta
20
+ * @param address - The address associated with the request.
21
+ * @param senderDid - The sender's decentralized identifier (DID).
22
+ * @param proofService - The proof service used to generate the proof.
23
+ * @returns A promise that resolves to an array of ZeroKnowledgeProofResponse objects.
24
+ */
25
+ export async function prepareAuthV2ZeroKnowledgeResponse(address, senderDid, proofService) {
26
+ const circuitId = CircuitId.AuthV2;
27
+ // this is now hardcoded calculated value for 'authV2' that can be changed in the future.
28
+ const id = 940499666;
29
+ if (isEthereumIdentity(senderDid)) {
30
+ return [
31
+ {
32
+ circuitId,
33
+ id,
34
+ pub_signals: [],
35
+ proof: {
36
+ pi_a: [],
37
+ pi_b: [],
38
+ pi_c: [],
39
+ protocol: 'groth16'
40
+ }
41
+ }
42
+ ];
43
+ }
44
+ const hash = Uint8Array.from([...hexToBytes(address), ...new Uint8Array(12)]).reverse();
45
+ const { proof, pub_signals } = await proofService.generateAuthV2Proof(hash, senderDid);
46
+ return [
47
+ {
48
+ circuitId,
49
+ id,
50
+ pub_signals,
51
+ proof
52
+ }
53
+ ];
54
+ }
@@ -1,4 +1,5 @@
1
1
  export * from './envelope';
2
2
  export * from './message';
3
3
  export * from './did';
4
+ export * from './contract-request.utils';
4
5
  export * from './accept-profile';
@@ -213,6 +213,12 @@ export class ProofService {
213
213
  authInputs.gistProof = gistProof;
214
214
  return authInputs.inputsMarshal();
215
215
  }
216
+ /** {@inheritdoc IProofService.generateAuthV2Proof} */
217
+ async generateAuthV2Proof(challenge, did) {
218
+ const authInputs = await this.generateAuthV2Inputs(challenge, did, CircuitId.AuthV2);
219
+ const zkProof = await this._prover.generate(authInputs, CircuitId.AuthV2);
220
+ return zkProof;
221
+ }
216
222
  async verifyState(circuitId, pubSignals, opts = {
217
223
  acceptedStateTransitionDelay: PROTOCOL_CONSTANTS.DEFAULT_AUTH_VERIFY_DELAY
218
224
  }) {
@@ -0,0 +1 @@
1
+ [{ "inputs": [{ "internalType": "uint256", "name": "initialSupply", "type": "uint256" }], "stateMutability": "nonpayable", "type": "constructor" }, { "inputs": [{ "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "allowance", "type": "uint256" }, { "internalType": "uint256", "name": "needed", "type": "uint256" }], "name": "ERC20InsufficientAllowance", "type": "error" }, { "inputs": [{ "internalType": "address", "name": "sender", "type": "address" }, { "internalType": "uint256", "name": "balance", "type": "uint256" }, { "internalType": "uint256", "name": "needed", "type": "uint256" }], "name": "ERC20InsufficientBalance", "type": "error" }, { "inputs": [{ "internalType": "address", "name": "approver", "type": "address" }], "name": "ERC20InvalidApprover", "type": "error" }, { "inputs": [{ "internalType": "address", "name": "receiver", "type": "address" }], "name": "ERC20InvalidReceiver", "type": "error" }, { "inputs": [{ "internalType": "address", "name": "sender", "type": "address" }], "name": "ERC20InvalidSender", "type": "error" }, { "inputs": [{ "internalType": "address", "name": "spender", "type": "address" }], "name": "ERC20InvalidSpender", "type": "error" }, { "anonymous": false, "inputs": [{ "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, { "indexed": true, "internalType": "address", "name": "spender", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" }], "name": "Approval", "type": "event" }, { "anonymous": false, "inputs": [{ "indexed": true, "internalType": "address", "name": "from", "type": "address" }, { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" }], "name": "Transfer", "type": "event" }, { "inputs": [{ "internalType": "address", "name": "owner", "type": "address" }, { "internalType": "address", "name": "spender", "type": "address" }], "name": "allowance", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "value", "type": "uint256" }], "name": "approve", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], "name": "balanceOf", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "decimals", "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "name", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "symbol", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "totalSupply", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "to", "type": "address" }, { "internalType": "uint256", "name": "value", "type": "uint256" }], "name": "transfer", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "from", "type": "address" }, { "internalType": "address", "name": "to", "type": "address" }, { "internalType": "uint256", "name": "value", "type": "uint256" }], "name": "transferFrom", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }]
@@ -0,0 +1,68 @@
1
+ import { Hash } from '@iden3/js-merkletree';
2
+ import { resolveDidDocument } from '../../utils';
3
+ import { DID, Id } from '@iden3/js-iden3-core';
4
+ import { JsonRpcProvider } from 'ethers';
5
+ export class DidResolverStateReadonlyStorage {
6
+ constructor(resolverUrl) {
7
+ this.resolverUrl = resolverUrl;
8
+ }
9
+ async getLatestStateById(id) {
10
+ return this.getStateInfo(id);
11
+ }
12
+ async getStateInfoByIdAndState(id, state) {
13
+ return this.getStateInfo(id, state);
14
+ }
15
+ async getGISTProof(id) {
16
+ const { didDocument } = await resolveDidDocument(DID.parseFromId(Id.fromBigInt(id)), this.resolverUrl);
17
+ const { global } = this.getIden3StateInfo2023(didDocument);
18
+ if (!global) {
19
+ throw new Error('GIST root not found');
20
+ }
21
+ const { proof } = global;
22
+ if (!proof) {
23
+ throw new Error('GIST proof not found');
24
+ }
25
+ return {
26
+ root: global.root,
27
+ existence: proof.existence,
28
+ siblings: proof.siblings?.map((sibling) => BigInt(sibling)),
29
+ index: BigInt(0),
30
+ value: BigInt(0),
31
+ auxExistence: !!proof.node_aux,
32
+ auxIndex: proof.node_aux ? BigInt(proof.node_aux.key) : BigInt(0),
33
+ auxValue: proof.node_aux ? BigInt(proof.node_aux.value) : BigInt(0)
34
+ };
35
+ }
36
+ async getGISTRootInfo(root, userId) {
37
+ const { didDocument } = await resolveDidDocument(DID.parseFromId(Id.fromBigInt(userId)), this.resolverUrl, {
38
+ gist: Hash.fromBigInt(root)
39
+ });
40
+ const { global } = this.getIden3StateInfo2023(didDocument);
41
+ if (!global) {
42
+ throw new Error('GIST root not found');
43
+ }
44
+ return global;
45
+ }
46
+ getRpcProvider() {
47
+ return new JsonRpcProvider();
48
+ }
49
+ publishState() {
50
+ throw new Error('publishState method not implemented.');
51
+ }
52
+ publishStateGeneric() {
53
+ throw new Error('publishStateGeneric method not implemented.');
54
+ }
55
+ async getStateInfo(id, state) {
56
+ const opts = state ? { state: Hash.fromBigInt(state) } : undefined;
57
+ const { didDocument } = await resolveDidDocument(DID.parseFromId(Id.fromBigInt(id)), this.resolverUrl, opts);
58
+ const { info } = this.getIden3StateInfo2023(didDocument);
59
+ return { ...info };
60
+ }
61
+ getIden3StateInfo2023(didDocument) {
62
+ const vm = didDocument.verificationMethod?.find((i) => i.type === 'Iden3StateInfo2023');
63
+ if (!vm) {
64
+ throw new Error('Iden3StateInfo2023 verification method not found');
65
+ }
66
+ return vm;
67
+ }
68
+ }
@@ -1,5 +1,6 @@
1
1
  import { Contract } from 'ethers';
2
- import abi from './abi/ERC20Permit.json';
2
+ import permitAbi from './abi/ERC20Permit.json';
3
+ import erc20Abi from './abi/ERC20.json';
3
4
  /**
4
5
  * @beta
5
6
  * getPermitSignature is a function to create EIP712 Permit signature
@@ -11,10 +12,11 @@ import abi from './abi/ERC20Permit.json';
11
12
  * @returns {Promise<PaymentRequestMessage>}
12
13
  */
13
14
  export async function getPermitSignature(signer, tokenAddress, spender, value, deadline) {
14
- const erc20PermitContract = new Contract(tokenAddress, abi, signer);
15
+ const erc20PermitContract = new Contract(tokenAddress, permitAbi, signer);
15
16
  const nonce = await erc20PermitContract.nonces(await signer.getAddress());
16
17
  const domainData = await erc20PermitContract.eip712Domain();
17
18
  const domain = {
19
+ name: domainData[1],
18
20
  version: domainData[2],
19
21
  chainId: domainData[3],
20
22
  verifyingContract: tokenAddress
@@ -37,3 +39,13 @@ export async function getPermitSignature(signer, tokenAddress, spender, value, d
37
39
  };
38
40
  return signer.signTypedData(domain, types, message);
39
41
  }
42
+ /**
43
+ * @beta
44
+ * getERC20Decimals is a function to retrieve the number of decimals of an ERC20 token
45
+ * @param {string} tokenAddress - Token address
46
+ * @param {ethers.ContractRunner} runner - Contract runner
47
+ */
48
+ export async function getERC20Decimals(tokenAddress, runner) {
49
+ const erc20Contract = new Contract(tokenAddress, erc20Abi, runner);
50
+ return erc20Contract.decimals();
51
+ }
@@ -1,4 +1,6 @@
1
1
  export * from './state';
2
2
  export * from './onchain-zkp-verifier';
3
3
  export * from './onchain-revocation';
4
- export * from './erc20-permit-sig';
4
+ export * from './onchain-issuer';
5
+ export * from './did-resolver-readonly-storage';
6
+ export * from './erc20-helper';