@0xpolygonid/js-sdk 1.33.0 → 1.33.3

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 (31) hide show
  1. package/dist/browser/esm/index.js +1123 -719
  2. package/dist/browser/esm/index.js.map +1 -1
  3. package/dist/browser/umd/index.global.js +182 -59
  4. package/dist/browser/umd/index.global.js.map +1 -1
  5. package/dist/node/cjs/index.cjs +1330 -915
  6. package/dist/node/cjs/index.cjs.map +1 -1
  7. package/dist/node/esm/index.js +1123 -719
  8. package/dist/node/esm/index.js.map +1 -1
  9. package/dist/types/iden3comm/handlers/credential-proposal.d.ts.map +1 -1
  10. package/dist/types/iden3comm/handlers/fetch.d.ts.map +1 -1
  11. package/dist/types/iden3comm/handlers/payment.d.ts +14 -5
  12. package/dist/types/iden3comm/handlers/payment.d.ts.map +1 -1
  13. package/dist/types/iden3comm/types/protocol/payment.d.ts +58 -9
  14. package/dist/types/iden3comm/types/protocol/payment.d.ts.map +1 -1
  15. package/dist/types/utils/index.d.ts +2 -0
  16. package/dist/types/utils/index.d.ts.map +1 -1
  17. package/dist/types/utils/payments/evm.d.ts +19 -0
  18. package/dist/types/utils/payments/evm.d.ts.map +1 -0
  19. package/dist/types/utils/payments/solana.d.ts +88 -0
  20. package/dist/types/utils/payments/solana.d.ts.map +1 -0
  21. package/dist/types/verifiable/constants.d.ts +16 -3
  22. package/dist/types/verifiable/constants.d.ts.map +1 -1
  23. package/package.json +5 -1
  24. package/src/iden3comm/handlers/credential-proposal.ts +4 -1
  25. package/src/iden3comm/handlers/fetch.ts +7 -1
  26. package/src/iden3comm/handlers/payment.ts +138 -131
  27. package/src/iden3comm/types/protocol/payment.ts +79 -10
  28. package/src/utils/index.ts +2 -0
  29. package/src/utils/payments/evm.ts +152 -0
  30. package/src/utils/payments/solana.ts +360 -0
  31. package/src/verifiable/constants.ts +17 -3
@@ -5,18 +5,21 @@ import { BasicMessage, IPackageManager, PackerParams } from '../types';
5
5
  import { DID, getUnixTimestamp } from '@iden3/js-iden3-core';
6
6
  import * as uuid from 'uuid';
7
7
  import { proving } from '@iden3/js-jwz';
8
- import { byteEncoder } from '../../utils';
8
+ import { buildSolanaPayment, byteEncoder, verifyIden3SolanaPaymentRequest } from '../../utils';
9
9
  import {
10
10
  AbstractMessageHandler,
11
11
  BasicHandlerOptions,
12
12
  IProtocolMessageHandler
13
13
  } from './message-handler';
14
14
  import {
15
- EthereumEip712Signature2021,
16
15
  Iden3PaymentCryptoV1,
17
16
  Iden3PaymentRailsERC20RequestV1,
18
17
  Iden3PaymentRailsERC20V1,
19
18
  Iden3PaymentRailsRequestV1,
19
+ Iden3PaymentRailsSolanaRequestV1,
20
+ Iden3PaymentRailsSolanaSPLRequestV1,
21
+ Iden3PaymentRailsSolanaSPLV1,
22
+ Iden3PaymentRailsSolanaV1,
20
23
  Iden3PaymentRailsV1,
21
24
  Iden3PaymentRequestCryptoV1,
22
25
  MultiChainPaymentConfig,
@@ -26,15 +29,12 @@ import {
26
29
  PaymentRequestTypeUnion,
27
30
  PaymentTypeUnion
28
31
  } from '../types/protocol/payment';
29
- import {
30
- PaymentFeatures,
31
- PaymentRequestDataType,
32
- PaymentType,
33
- SupportedPaymentProofType
34
- } from '../../verifiable';
35
- import { Signer, ethers } from 'ethers';
32
+ import { PaymentFeatures, PaymentRequestDataType, PaymentType } from '../../verifiable';
33
+ import { Signer } from 'ethers';
36
34
  import { Resolvable } from 'did-resolver';
37
35
  import { verifyExpiresTime } from './common';
36
+ import { Keypair } from '@solana/web3.js';
37
+ import { buildEvmPayment, verifyEIP712TypedData } from '../../utils/payments/evm';
38
38
 
39
39
  /** @beta PaymentRequestCreationOptions represents payment-request creation options */
40
40
  export type PaymentRequestCreationOptions = {
@@ -46,6 +46,12 @@ export type PaymentCreationOptions = {
46
46
  expires_time?: Date;
47
47
  };
48
48
 
49
+ /** @beta CreatePaymentRailsV1Options holds options for PaymentRailsV1 creation */
50
+ export type CreatePaymentRailsV1Options = {
51
+ ethSigner?: Signer;
52
+ solSigner?: Keypair;
53
+ };
54
+
49
55
  /**
50
56
  * @beta
51
57
  * createPaymentRequest is a function to create protocol payment-request message
@@ -80,55 +86,6 @@ export function createPaymentRequest(
80
86
  return request;
81
87
  }
82
88
 
83
- export async function verifyEIP712TypedData(
84
- data: Iden3PaymentRailsRequestV1 | Iden3PaymentRailsERC20RequestV1,
85
- resolver: Resolvable
86
- ): Promise<string> {
87
- const paymentData =
88
- data.type === PaymentRequestDataType.Iden3PaymentRailsRequestV1
89
- ? {
90
- recipient: data.recipient,
91
- amount: data.amount,
92
- expirationDate: getUnixTimestamp(new Date(data.expirationDate)),
93
- nonce: data.nonce,
94
- metadata: '0x'
95
- }
96
- : {
97
- tokenAddress: data.tokenAddress,
98
- recipient: data.recipient,
99
- amount: data.amount,
100
- expirationDate: getUnixTimestamp(new Date(data.expirationDate)),
101
- nonce: data.nonce,
102
- metadata: '0x'
103
- };
104
- const proof = Array.isArray(data.proof) ? data.proof[0] : data.proof;
105
- const typesFetchResult = await fetch(proof.eip712.types);
106
- const types = await typesFetchResult.json();
107
- delete types.EIP712Domain;
108
- const recovered = ethers.verifyTypedData(
109
- proof.eip712.domain,
110
- types,
111
- paymentData,
112
- proof.proofValue
113
- );
114
-
115
- const { didDocument } = await resolver.resolve(proof.verificationMethod);
116
- if (didDocument?.verificationMethod) {
117
- for (const verificationMethod of didDocument.verificationMethod) {
118
- if (
119
- verificationMethod.blockchainAccountId?.split(':').slice(-1)[0].toLowerCase() ===
120
- recovered.toLowerCase()
121
- ) {
122
- return recovered;
123
- }
124
- }
125
- } else {
126
- throw new Error('failed request. issuer DIDDocument does not contain any verificationMethods');
127
- }
128
-
129
- throw new Error(`failed request. no matching verificationMethod`);
130
- }
131
-
132
89
  /**
133
90
  * @beta
134
91
  * PaymentRailsInfo represents payment info for payment rails
@@ -227,16 +184,18 @@ export interface IPaymentHandler {
227
184
  * @param {DID} sender - sender did
228
185
  * @param {DID} receiver - receiver did
229
186
  * @param {string} agent - agent URL
230
- * @param {Signer} signer - receiver did
187
+ * @param {Signer} signer - ETH signer
231
188
  * @param payments - payment options
189
+ * @param {CreatePaymentRailsV1Options} createOptions - options for payment rails creation
232
190
  * @returns {Promise<PaymentRequestMessage>}
233
191
  */
234
192
  createPaymentRailsV1(
235
193
  sender: DID,
236
194
  receiver: DID,
237
195
  agent: string,
238
- signer: Signer,
239
- payments: PaymentRailsInfo[]
196
+ signer: Signer, // the same as createOptions.ethSigner (for compatibility)
197
+ payments: PaymentRailsInfo[],
198
+ createOptions?: CreatePaymentRailsV1Options
240
199
  ): Promise<PaymentRequestMessage>;
241
200
  }
242
201
 
@@ -380,6 +339,22 @@ export class PaymentHandler
380
339
  )
381
340
  );
382
341
  break;
342
+ case PaymentRequestDataType.Iden3PaymentRailsSolanaRequestV1:
343
+ payments.push(
344
+ await this.handleIden3PaymentRailsSolanaRequestV1(selectedPayment, ctx.paymentHandler)
345
+ );
346
+ break;
347
+ case PaymentRequestDataType.Iden3PaymentRailsSolanaSPLRequestV1:
348
+ payments.push(
349
+ await this.handleIden3PaymentRailsSolanaSPLRequestV1(
350
+ {
351
+ ...selectedPayment,
352
+ type: PaymentRequestDataType.Iden3PaymentRailsSolanaSPLRequestV1
353
+ },
354
+ ctx.paymentHandler
355
+ )
356
+ );
357
+ break;
383
358
  }
384
359
  }
385
360
 
@@ -490,12 +465,18 @@ export class PaymentHandler
490
465
  receiver: DID,
491
466
  agent: string,
492
467
  signer: Signer,
493
- payments: PaymentRailsInfo[]
468
+ payments: PaymentRailsInfo[],
469
+ createOptions?: CreatePaymentRailsV1Options
494
470
  ): Promise<PaymentRequestMessage> {
495
471
  const paymentRequestInfo: PaymentRequestInfo[] = [];
496
472
  for (let i = 0; i < payments.length; i++) {
497
473
  const { credentials, description } = payments[i];
498
- const dataArr: (Iden3PaymentRailsRequestV1 | Iden3PaymentRailsERC20RequestV1)[] = [];
474
+ const dataArr: (
475
+ | Iden3PaymentRailsRequestV1
476
+ | Iden3PaymentRailsERC20RequestV1
477
+ | Iden3PaymentRailsSolanaRequestV1
478
+ | Iden3PaymentRailsSolanaSPLRequestV1
479
+ )[] = [];
499
480
  for (let j = 0; j < payments[i].options.length; j++) {
500
481
  const { nonce, amount, chainId, optionId, expirationDate } = payments[i].options[j];
501
482
 
@@ -512,82 +493,51 @@ export class PaymentHandler
512
493
  throw new Error(`failed request. no option for id ${optionId}`);
513
494
  }
514
495
  if (
515
- option.type === PaymentRequestDataType.Iden3PaymentRailsERC20RequestV1 &&
496
+ (option.type === PaymentRequestDataType.Iden3PaymentRailsERC20RequestV1 ||
497
+ option.type === PaymentRequestDataType.Iden3PaymentRailsSolanaSPLRequestV1) &&
516
498
  !option.contractAddress
517
499
  ) {
518
500
  throw new Error(`failed request. no token address for option id ${optionId}`);
519
501
  }
520
502
  const expirationDateRequired =
521
503
  expirationDate ?? new Date(new Date().setHours(new Date().getHours() + 1));
522
- const typeUrl = `https://schema.iden3.io/core/json/${option.type}.json`;
523
- const typesFetchResult = await fetch(typeUrl);
524
- const types = await typesFetchResult.json();
525
- delete types.EIP712Domain;
526
-
527
- const paymentData =
528
- option.type === PaymentRequestDataType.Iden3PaymentRailsRequestV1
529
- ? {
530
- recipient,
531
- amount: amount,
532
- expirationDate: getUnixTimestamp(expirationDateRequired),
533
- nonce,
534
- metadata: '0x'
535
- }
536
- : {
537
- tokenAddress: option.contractAddress,
538
- recipient,
539
- amount: amount,
540
- expirationDate: getUnixTimestamp(expirationDateRequired),
541
- nonce,
542
- metadata: '0x'
543
- };
544
-
545
- const domain = {
546
- name: 'MCPayment',
547
- version: '1.0.0',
548
- chainId,
549
- verifyingContract: paymentRails
550
- };
551
- const signature = await signer.signTypedData(domain, types, paymentData);
552
- const proof: EthereumEip712Signature2021[] = [
553
- {
554
- type: SupportedPaymentProofType.EthereumEip712Signature2021,
555
- proofPurpose: 'assertionMethod',
556
- proofValue: signature,
557
- verificationMethod: `did:pkh:eip155:${chainId}:${await signer.getAddress()}`,
558
- created: new Date().toISOString(),
559
- eip712: {
560
- types: typeUrl,
561
- primaryType: 'Iden3PaymentRailsRequestV1',
562
- domain
563
- }
504
+
505
+ if (
506
+ option.type === PaymentRequestDataType.Iden3PaymentRailsSolanaRequestV1 ||
507
+ option.type === PaymentRequestDataType.Iden3PaymentRailsSolanaSPLRequestV1
508
+ ) {
509
+ if (!createOptions?.solSigner) {
510
+ throw new Error(
511
+ `please provide solana signer in context for ${option.type} payment type`
512
+ );
564
513
  }
565
- ];
566
-
567
- const d: Iden3PaymentRailsRequestV1 = {
568
- type: PaymentRequestDataType.Iden3PaymentRailsRequestV1,
569
- '@context': [
570
- `https://schema.iden3.io/core/jsonld/payment.jsonld#${option.type}`,
571
- 'https://w3id.org/security/suites/eip712sig-2021/v1'
572
- ],
573
- recipient,
574
- amount: amount.toString(),
575
- expirationDate: expirationDateRequired.toISOString(),
576
- nonce: nonce.toString(),
577
- metadata: '0x',
578
- proof
579
- };
580
- dataArr.push(
581
- option.type === PaymentRequestDataType.Iden3PaymentRailsRequestV1
582
- ? d
583
- : {
584
- ...d,
585
- type: option.type,
586
- tokenAddress: option.contractAddress || '',
587
- features: option.features || []
588
- }
589
- );
514
+
515
+ const payment = await buildSolanaPayment(
516
+ createOptions.solSigner,
517
+ option,
518
+ chainId,
519
+ paymentRails,
520
+ recipient,
521
+ BigInt(amount),
522
+ expirationDateRequired,
523
+ nonce
524
+ );
525
+ dataArr.push(payment);
526
+ } else {
527
+ const payment = await buildEvmPayment(
528
+ signer,
529
+ option,
530
+ chainId,
531
+ paymentRails,
532
+ recipient,
533
+ BigInt(amount),
534
+ expirationDateRequired,
535
+ nonce
536
+ );
537
+ dataArr.push(payment);
538
+ }
590
539
  }
540
+
591
541
  paymentRequestInfo.push({
592
542
  data: dataArr,
593
543
  credentials,
@@ -654,6 +604,63 @@ export class PaymentHandler
654
604
  };
655
605
  }
656
606
 
607
+ private async handleIden3PaymentRailsSolanaRequestV1(
608
+ data: Iden3PaymentRailsSolanaRequestV1,
609
+ paymentHandler: (data: Iden3PaymentRailsSolanaRequestV1) => Promise<string>
610
+ ): Promise<Iden3PaymentRailsSolanaV1> {
611
+ if (data.expirationDate && new Date(data.expirationDate) < new Date()) {
612
+ throw new Error(`failed request. expired request`);
613
+ }
614
+ const isValid = await verifyIden3SolanaPaymentRequest(data, this._params.documentResolver);
615
+ if (!isValid) {
616
+ throw new Error(`failed request. invalid Solana payment request signature`);
617
+ }
618
+ const proof = Array.isArray(data.proof) ? data.proof[0] : data.proof;
619
+ const signer = proof.verificationMethod.split(':').slice(-1)[0];
620
+ if (this._params.allowedSigners && !this._params.allowedSigners.includes(signer)) {
621
+ throw new Error(`failed request. signer is not in the allowed signers list`);
622
+ }
623
+ const txId = await paymentHandler(data);
624
+ return {
625
+ nonce: data.nonce,
626
+ type: PaymentType.Iden3PaymentRailsSolanaV1,
627
+ '@context': 'https://schema.iden3.io/core/jsonld/payment.jsonld#Iden3PaymentRailsSolanaV1',
628
+ paymentData: {
629
+ txId,
630
+ chainId: proof.domain.chainId
631
+ }
632
+ };
633
+ }
634
+
635
+ private async handleIden3PaymentRailsSolanaSPLRequestV1(
636
+ data: Iden3PaymentRailsSolanaSPLRequestV1,
637
+ paymentHandler: (data: Iden3PaymentRailsSolanaSPLRequestV1) => Promise<string>
638
+ ): Promise<Iden3PaymentRailsSolanaSPLV1> {
639
+ if (data.expirationDate && new Date(data.expirationDate) < new Date()) {
640
+ throw new Error(`failed request. expired request`);
641
+ }
642
+ const isValid = await verifyIden3SolanaPaymentRequest(data, this._params.documentResolver);
643
+ if (!isValid) {
644
+ throw new Error(`failed request. invalid Solana payment request signature`);
645
+ }
646
+ const proof = Array.isArray(data.proof) ? data.proof[0] : data.proof;
647
+ const signer = proof.verificationMethod.split(':').slice(-1)[0];
648
+ if (this._params.allowedSigners && !this._params.allowedSigners.includes(signer)) {
649
+ throw new Error(`failed request. signer is not in the allowed signers list`);
650
+ }
651
+ const txId = await paymentHandler(data);
652
+ return {
653
+ nonce: data.nonce,
654
+ type: PaymentType.Iden3PaymentRailsSolanaSPLV1,
655
+ '@context': 'https://schema.iden3.io/core/jsonld/payment.jsonld#Iden3PaymentRailsSolanaSPLV1',
656
+ paymentData: {
657
+ txId,
658
+ chainId: proof.domain.chainId,
659
+ tokenAddress: data.tokenAddress
660
+ }
661
+ };
662
+ }
663
+
657
664
  private async handleIden3PaymentRailsERC20RequestV1(
658
665
  data: Iden3PaymentRailsERC20RequestV1,
659
666
  paymentHandler: (data: Iden3PaymentRailsERC20RequestV1) => Promise<string>,
@@ -31,6 +31,8 @@ export type PaymentRequestInfo = {
31
31
  | Iden3PaymentRequestCryptoV1
32
32
  | Iden3PaymentRailsRequestV1
33
33
  | Iden3PaymentRailsERC20RequestV1
34
+ | Iden3PaymentRailsSolanaRequestV1
35
+ | Iden3PaymentRailsSolanaSPLRequestV1
34
36
  )[];
35
37
  description?: string;
36
38
  };
@@ -47,6 +49,7 @@ export type Iden3PaymentRequestCryptoV1 = {
47
49
  expiration?: string;
48
50
  };
49
51
 
52
+ /** @beta Iden3PaymentRailsRequestV1 is struct the represents EVM native payment rails request */
50
53
  export type Iden3PaymentRailsRequestV1 = {
51
54
  type: PaymentRequestDataType.Iden3PaymentRailsRequestV1;
52
55
  '@context': string | (string | object)[];
@@ -58,12 +61,32 @@ export type Iden3PaymentRailsRequestV1 = {
58
61
  proof: EthereumEip712Signature2021 | EthereumEip712Signature2021[];
59
62
  };
60
63
 
64
+ /** @beta Iden3PaymentRailsERC20RequestV1 is struct the represents EVM ERC 20 payment rails request */
61
65
  export type Iden3PaymentRailsERC20RequestV1 = Omit<Required<Iden3PaymentRailsRequestV1>, 'type'> & {
62
66
  tokenAddress: string;
63
67
  features?: PaymentFeatures[];
64
68
  type: PaymentRequestDataType.Iden3PaymentRailsERC20RequestV1;
65
69
  };
66
70
 
71
+ /** @beta Iden3PaymentRailsSolanaRequestV1 is struct the represents Solana native payment rails request */
72
+ export type Iden3PaymentRailsSolanaRequestV1 = Omit<
73
+ Required<Iden3PaymentRailsRequestV1>,
74
+ 'type' | 'proof'
75
+ > & {
76
+ type: PaymentRequestDataType.Iden3PaymentRailsSolanaRequestV1;
77
+ proof: Iden3SolanaEd25519SignatureV1 | Iden3SolanaEd25519SignatureV1[];
78
+ };
79
+
80
+ /** @beta Iden3PaymentRailsSolanaSPLRequestV1 is struct the represents Solana SPL payment rails request */
81
+ export type Iden3PaymentRailsSolanaSPLRequestV1 = Omit<
82
+ Required<Iden3PaymentRailsERC20RequestV1>,
83
+ 'type' | 'proof'
84
+ > & {
85
+ type: PaymentRequestDataType.Iden3PaymentRailsSolanaSPLRequestV1;
86
+ proof: Iden3SolanaEd25519SignatureV1 | Iden3SolanaEd25519SignatureV1[];
87
+ };
88
+
89
+ /** @beta EthereumEip712Signature2021 is struct the represents EIP-712 signature for Ethereum */
67
90
  export type EthereumEip712Signature2021 = {
68
91
  type: SupportedPaymentProofType.EthereumEip712Signature2021;
69
92
  proofPurpose: string;
@@ -82,6 +105,20 @@ export type EthereumEip712Signature2021 = {
82
105
  };
83
106
  };
84
107
 
108
+ /** @beta Iden3SolanaEd25519SignatureV1 is struct the represents Ed25519 signature for Solana Payment Instruction */
109
+ export type Iden3SolanaEd25519SignatureV1 = {
110
+ type: SupportedPaymentProofType.SolanaEd25519Signature2025;
111
+ proofPurpose: string;
112
+ proofValue: string;
113
+ created: string;
114
+ verificationMethod: string;
115
+ domain: {
116
+ version: 'SolanaEd25519NativeV1' | 'SolanaEd25519SPLV1';
117
+ chainId: string;
118
+ verifyingContract: string;
119
+ };
120
+ };
121
+
85
122
  /** @beta PaymentMessage is struct the represents payment message */
86
123
  export type PaymentMessage = BasicMessage & {
87
124
  body: PaymentMessageBody;
@@ -128,19 +165,47 @@ export type Iden3PaymentRailsERC20V1 = {
128
165
  };
129
166
  };
130
167
 
168
+ /** @beta Iden3PaymentRailsSolanaV1 is struct the represents payment info for Iden3PaymentRailsSolanaV1 */
169
+ export type Iden3PaymentRailsSolanaV1 = {
170
+ nonce: string;
171
+ type: 'Iden3PaymentRailsSolanaV1';
172
+ '@context': string | (string | object)[];
173
+ paymentData: {
174
+ txId: string;
175
+ chainId: string;
176
+ };
177
+ };
178
+
179
+ /** @beta Iden3PaymentRailsSolanaSPLV1 is struct the represents payment info for Iden3PaymentRailsSolanaSPLV1 */
180
+ export type Iden3PaymentRailsSolanaSPLV1 = {
181
+ nonce: string;
182
+ type: 'Iden3PaymentRailsSolanaSPLV1';
183
+ '@context': string | (string | object)[];
184
+ paymentData: {
185
+ txId: string;
186
+ chainId: string;
187
+ tokenAddress: string;
188
+ };
189
+ };
190
+
131
191
  /** @beta MultiChainPaymentConfig is struct that represents payments contracts information for different chains */
132
192
  export type MultiChainPaymentConfig = {
133
193
  chainId: string;
134
194
  paymentRails: string;
135
195
  recipient: string;
136
- options: {
137
- id: string;
138
- type:
139
- | PaymentRequestDataType.Iden3PaymentRailsRequestV1
140
- | PaymentRequestDataType.Iden3PaymentRailsERC20RequestV1;
141
- contractAddress?: string;
142
- features?: PaymentFeatures[];
143
- }[];
196
+ options: MultiChainPaymentConfigOption[];
197
+ };
198
+
199
+ /** @beta MultiChainPaymentConfigOption is struct that represents payment options for different chains */
200
+ export type MultiChainPaymentConfigOption = {
201
+ id: string;
202
+ type:
203
+ | PaymentRequestDataType.Iden3PaymentRailsRequestV1
204
+ | PaymentRequestDataType.Iden3PaymentRailsERC20RequestV1
205
+ | PaymentRequestDataType.Iden3PaymentRailsSolanaRequestV1
206
+ | PaymentRequestDataType.Iden3PaymentRailsSolanaSPLRequestV1;
207
+ contractAddress?: string;
208
+ features?: PaymentFeatures[];
144
209
  };
145
210
 
146
211
  /**
@@ -150,7 +215,9 @@ export type MultiChainPaymentConfig = {
150
215
  export type PaymentRequestTypeUnion =
151
216
  | Iden3PaymentRequestCryptoV1
152
217
  | Iden3PaymentRailsRequestV1
153
- | Iden3PaymentRailsERC20RequestV1;
218
+ | Iden3PaymentRailsERC20RequestV1
219
+ | Iden3PaymentRailsSolanaRequestV1
220
+ | Iden3PaymentRailsSolanaSPLRequestV1;
154
221
 
155
222
  /**
156
223
  * @beta
@@ -159,4 +226,6 @@ export type PaymentRequestTypeUnion =
159
226
  export type PaymentTypeUnion =
160
227
  | Iden3PaymentCryptoV1
161
228
  | Iden3PaymentRailsV1
162
- | Iden3PaymentRailsERC20V1;
229
+ | Iden3PaymentRailsERC20V1
230
+ | Iden3PaymentRailsSolanaV1
231
+ | Iden3PaymentRailsSolanaSPLV1;
@@ -3,3 +3,5 @@ export * from './object';
3
3
  export * from './did-helper';
4
4
  export * from './message-bus';
5
5
  export * from './compare-func';
6
+ export * from './payments/solana';
7
+ export * from './payments/evm';
@@ -0,0 +1,152 @@
1
+ import { Signer, ethers } from 'ethers';
2
+ import {
3
+ EthereumEip712Signature2021,
4
+ Iden3PaymentRailsERC20RequestV1,
5
+ Iden3PaymentRailsRequestV1,
6
+ MultiChainPaymentConfigOption
7
+ } from '../../iden3comm';
8
+ import { PaymentRequestDataType, SupportedPaymentProofType } from '../../verifiable';
9
+ import { getUnixTimestamp } from '@iden3/js-iden3-core';
10
+ import { Resolvable } from 'did-resolver';
11
+
12
+ /**
13
+ * @beta
14
+ * buildEvmPayment creates an EVM-based payment request and signs it using EIP-712.
15
+ * @param {Signer} signer - EIP-712 compatible signer
16
+ * @param {MultiChainPaymentConfigOption} option - payment option configuration
17
+ * @param {string} chainId - EVM chain ID
18
+ * @param {string} paymentRails - payment rails contract address
19
+ * @param {string} recipient - recipient address
20
+ * @param {bigint} amount - payment amount in smallest units
21
+ * @param {Date} expirationDateRequired - expiration date
22
+ * @param {bigint} nonce - unique nonce for the payment
23
+ * @returns {Promise<Iden3PaymentRailsRequestV1 | Iden3PaymentRailsERC20RequestV1>} payment request object
24
+ */
25
+ export const buildEvmPayment = async (
26
+ signer: Signer,
27
+ option: MultiChainPaymentConfigOption,
28
+ chainId: string,
29
+ paymentRails: string,
30
+ recipient: string,
31
+ amount: bigint,
32
+ expirationDateRequired: Date,
33
+ nonce: bigint
34
+ ): Promise<Iden3PaymentRailsRequestV1 | Iden3PaymentRailsERC20RequestV1> => {
35
+ const typeUrl = `https://schema.iden3.io/core/json/${option.type}.json`;
36
+ const typesFetchResult = await fetch(typeUrl);
37
+ const types = await typesFetchResult.json();
38
+ delete types.EIP712Domain;
39
+ const paymentData =
40
+ option.type === PaymentRequestDataType.Iden3PaymentRailsRequestV1
41
+ ? {
42
+ recipient,
43
+ amount: amount,
44
+ expirationDate: getUnixTimestamp(expirationDateRequired),
45
+ nonce,
46
+ metadata: '0x'
47
+ }
48
+ : {
49
+ tokenAddress: option.contractAddress,
50
+ recipient,
51
+ amount: amount,
52
+ expirationDate: getUnixTimestamp(expirationDateRequired),
53
+ nonce,
54
+ metadata: '0x'
55
+ };
56
+
57
+ const domain = {
58
+ name: 'MCPayment',
59
+ version: '1.0.0',
60
+ chainId,
61
+ verifyingContract: paymentRails
62
+ };
63
+
64
+ const signature = await signer.signTypedData(domain, types, paymentData);
65
+
66
+ const proof: EthereumEip712Signature2021[] = [
67
+ {
68
+ type: SupportedPaymentProofType.EthereumEip712Signature2021,
69
+ proofPurpose: 'assertionMethod',
70
+ proofValue: signature,
71
+ verificationMethod: `did:pkh:eip155:${chainId}:${await signer.getAddress()}`,
72
+ created: new Date().toISOString(),
73
+ eip712: {
74
+ types: typeUrl,
75
+ primaryType: 'Iden3PaymentRailsRequestV1',
76
+ domain
77
+ }
78
+ }
79
+ ];
80
+ const d: Iden3PaymentRailsRequestV1 = {
81
+ type: PaymentRequestDataType.Iden3PaymentRailsRequestV1,
82
+ '@context': [
83
+ `https://schema.iden3.io/core/jsonld/payment.jsonld#${option.type}`,
84
+ 'https://w3id.org/security/suites/eip712sig-2021/v1'
85
+ ],
86
+ recipient,
87
+ amount: amount.toString(),
88
+ expirationDate: expirationDateRequired.toISOString(),
89
+ nonce: nonce.toString(),
90
+ metadata: '0x',
91
+ proof
92
+ };
93
+
94
+ if (option.type === PaymentRequestDataType.Iden3PaymentRailsRequestV1) {
95
+ return d;
96
+ }
97
+ return {
98
+ ...d,
99
+ type: option.type,
100
+ tokenAddress: option.contractAddress || '',
101
+ features: option.features || []
102
+ } as Iden3PaymentRailsERC20RequestV1;
103
+ };
104
+
105
+ export async function verifyEIP712TypedData(
106
+ data: Iden3PaymentRailsRequestV1 | Iden3PaymentRailsERC20RequestV1,
107
+ resolver: Resolvable
108
+ ): Promise<string> {
109
+ const paymentData =
110
+ data.type === PaymentRequestDataType.Iden3PaymentRailsRequestV1
111
+ ? {
112
+ recipient: data.recipient,
113
+ amount: data.amount,
114
+ expirationDate: getUnixTimestamp(new Date(data.expirationDate)),
115
+ nonce: data.nonce,
116
+ metadata: '0x'
117
+ }
118
+ : {
119
+ tokenAddress: data.tokenAddress,
120
+ recipient: data.recipient,
121
+ amount: data.amount,
122
+ expirationDate: getUnixTimestamp(new Date(data.expirationDate)),
123
+ nonce: data.nonce,
124
+ metadata: '0x'
125
+ };
126
+ const proof = Array.isArray(data.proof) ? data.proof[0] : data.proof;
127
+ const typesFetchResult = await fetch(proof.eip712.types);
128
+ const types = await typesFetchResult.json();
129
+ delete types.EIP712Domain;
130
+ const recovered = ethers.verifyTypedData(
131
+ proof.eip712.domain,
132
+ types,
133
+ paymentData,
134
+ proof.proofValue
135
+ );
136
+
137
+ const { didDocument } = await resolver.resolve(proof.verificationMethod);
138
+ if (didDocument?.verificationMethod) {
139
+ for (const verificationMethod of didDocument.verificationMethod) {
140
+ if (
141
+ verificationMethod.blockchainAccountId?.split(':').slice(-1)[0].toLowerCase() ===
142
+ recovered.toLowerCase()
143
+ ) {
144
+ return recovered;
145
+ }
146
+ }
147
+ } else {
148
+ throw new Error('failed request. issuer DIDDocument does not contain any verificationMethods');
149
+ }
150
+
151
+ throw new Error(`failed request. no matching verificationMethod`);
152
+ }