@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
@@ -0,0 +1,360 @@
1
+ import { Schema, serialize } from 'borsh';
2
+ import {
3
+ Iden3PaymentRailsSolanaRequestV1,
4
+ Iden3PaymentRailsSolanaSPLRequestV1,
5
+ Iden3SolanaEd25519SignatureV1,
6
+ MultiChainPaymentConfigOption
7
+ } from '../../iden3comm';
8
+ import { ed25519 } from '@noble/curves/ed25519';
9
+ import {
10
+ PaymentRequestDataType,
11
+ SOLANA_CHAIN_REF,
12
+ SupportedPaymentProofType
13
+ } from '../../verifiable';
14
+ import { byteEncoder } from '../encoding';
15
+ import { getUnixTimestamp } from '@iden3/js-iden3-core';
16
+ import { Keypair, PublicKey } from '@solana/web3.js';
17
+ import { Resolvable } from 'did-resolver';
18
+
19
+ export class SolanaNativePaymentRequest {
20
+ version: Uint8Array;
21
+ chainId: bigint;
22
+ verifyingContract: Uint8Array;
23
+ recipient: Uint8Array;
24
+ amount: bigint;
25
+ expirationDate: bigint;
26
+ nonce: bigint;
27
+ metadata: Uint8Array;
28
+
29
+ constructor(fields: {
30
+ version: Uint8Array;
31
+ chainId: bigint;
32
+ verifyingContract: Uint8Array;
33
+ recipient: Uint8Array;
34
+ amount: bigint;
35
+ expirationDate: bigint;
36
+ nonce: bigint;
37
+ metadata: Uint8Array;
38
+ }) {
39
+ this.version = fields.version;
40
+ this.chainId = fields.chainId;
41
+ this.verifyingContract = fields.verifyingContract;
42
+ this.recipient = fields.recipient;
43
+ this.amount = fields.amount;
44
+ this.expirationDate = fields.expirationDate;
45
+ this.nonce = fields.nonce;
46
+ this.metadata = fields.metadata;
47
+ }
48
+ }
49
+
50
+ export class SolanaSplPaymentRequest {
51
+ version: Uint8Array;
52
+ chainId: bigint;
53
+ verifyingContract: Uint8Array;
54
+ tokenAddress: Uint8Array;
55
+ recipient: Uint8Array;
56
+ amount: bigint;
57
+ expirationDate: bigint;
58
+ nonce: bigint;
59
+ metadata: Uint8Array;
60
+
61
+ constructor(fields: {
62
+ version: Uint8Array;
63
+ chainId: bigint;
64
+ verifyingContract: Uint8Array;
65
+ tokenAddress: Uint8Array;
66
+ recipient: Uint8Array;
67
+ amount: bigint;
68
+ expirationDate: bigint;
69
+ nonce: bigint;
70
+ metadata: Uint8Array;
71
+ }) {
72
+ this.version = fields.version;
73
+ this.chainId = fields.chainId;
74
+ this.verifyingContract = fields.verifyingContract;
75
+ this.tokenAddress = fields.tokenAddress;
76
+ this.recipient = fields.recipient;
77
+ this.amount = fields.amount;
78
+ this.expirationDate = fields.expirationDate;
79
+ this.nonce = fields.nonce;
80
+ this.metadata = fields.metadata;
81
+ }
82
+ }
83
+
84
+ export const SolanaNativePaymentSchema = new Map([
85
+ [
86
+ SolanaNativePaymentRequest,
87
+ {
88
+ kind: 'struct',
89
+ fields: [
90
+ ['version', ['u8']],
91
+ ['chainId', 'u64'],
92
+ ['verifyingContract', ['u8', 32]],
93
+ ['recipient', ['u8', 32]],
94
+ ['amount', 'u64'],
95
+ ['expirationDate', 'u64'],
96
+ ['nonce', 'u64'],
97
+ ['metadata', ['u8']]
98
+ ]
99
+ }
100
+ ]
101
+ ]);
102
+
103
+ export const SolanaSplPaymentSchema = new Map([
104
+ [
105
+ SolanaSplPaymentRequest,
106
+ {
107
+ kind: 'struct',
108
+ fields: [
109
+ ['version', ['u8']],
110
+ ['chainId', 'u64'],
111
+ ['verifyingContract', ['u8', 32]],
112
+ ['tokenAddress', ['u8', 32]],
113
+ ['recipient', ['u8', 32]],
114
+ ['amount', 'u64'],
115
+ ['expirationDate', 'u64'],
116
+ ['nonce', 'u64'],
117
+ ['metadata', ['u8']]
118
+ ]
119
+ }
120
+ ]
121
+ ]);
122
+
123
+ export class SolanaPaymentInstruction {
124
+ recipient: Uint8Array;
125
+ amount: bigint;
126
+ expiration_date: bigint;
127
+ nonce: bigint;
128
+ metadata: Uint8Array;
129
+ signature: Uint8Array;
130
+
131
+ constructor(fields: {
132
+ recipient: Uint8Array;
133
+ amount: bigint;
134
+ expiration_date: bigint;
135
+ nonce: bigint;
136
+ metadata: Uint8Array;
137
+ signature: Uint8Array;
138
+ }) {
139
+ this.recipient = fields.recipient;
140
+ this.amount = fields.amount;
141
+ this.expiration_date = fields.expiration_date;
142
+ this.nonce = fields.nonce;
143
+ this.metadata = fields.metadata;
144
+ this.signature = fields.signature;
145
+ }
146
+ }
147
+
148
+ export const SolanaPaymentInstructionSchema: Schema = new Map([
149
+ [
150
+ SolanaPaymentInstruction,
151
+ {
152
+ kind: 'struct',
153
+ fields: [
154
+ ['recipient', ['u8', 32]],
155
+ ['amount', 'u64'],
156
+ ['expiration_date', 'u64'],
157
+ ['nonce', 'u64'],
158
+ ['metadata', ['u8']],
159
+ ['signature', [64]]
160
+ ]
161
+ }
162
+ ]
163
+ ]);
164
+
165
+ /**
166
+ * @beta
167
+ * buildSolanaPayment creates an Solana-based payment request and signs it using ed25519.
168
+ * @param {Keypair} solSigner - Keypair for signing the payment request
169
+ * @param {MultiChainPaymentConfigOption} option - payment option configuration
170
+ * @param {string} chainId - EVM chain ID
171
+ * @param {string} paymentRails - payment rails contract address
172
+ * @param {string} recipient - recipient address
173
+ * @param {bigint} amount - payment amount in smallest units
174
+ * @param {Date} expirationDateRequired - expiration date
175
+ * @param {bigint} nonce - unique nonce for the payment
176
+ * @returns {Promise<Iden3PaymentRailsSolanaRequestV1 | Iden3PaymentRailsSolanaSPLRequestV1>} payment request object
177
+ */
178
+ export const buildSolanaPayment = async (
179
+ solSigner: Keypair,
180
+ option: MultiChainPaymentConfigOption,
181
+ chainId: string,
182
+ paymentRails: string,
183
+ recipient: string,
184
+ amount: bigint,
185
+ expirationDate: Date,
186
+ nonce: bigint
187
+ ): Promise<Iden3PaymentRailsSolanaRequestV1 | Iden3PaymentRailsSolanaSPLRequestV1> => {
188
+ let serialized: Uint8Array;
189
+ const proofVersion =
190
+ option.type === PaymentRequestDataType.Iden3PaymentRailsSolanaRequestV1
191
+ ? 'SolanaEd25519NativeV1'
192
+ : 'SolanaEd25519SPLV1';
193
+ let chainRef = chainId;
194
+ switch (chainId) {
195
+ case '101':
196
+ chainRef = SOLANA_CHAIN_REF.DEVNET;
197
+ break;
198
+ case '102':
199
+ chainRef = SOLANA_CHAIN_REF.TESTNET;
200
+ break;
201
+ case '103':
202
+ chainRef = SOLANA_CHAIN_REF.MAINNET;
203
+ break;
204
+ }
205
+ if (option.type === PaymentRequestDataType.Iden3PaymentRailsSolanaRequestV1) {
206
+ const request = new SolanaNativePaymentRequest({
207
+ version: byteEncoder.encode(proofVersion),
208
+ chainId: BigInt(chainId),
209
+ verifyingContract: new PublicKey(paymentRails).toBytes(),
210
+ recipient: new PublicKey(recipient).toBytes(),
211
+ amount: BigInt(amount),
212
+ expirationDate: BigInt(getUnixTimestamp(expirationDate)),
213
+ nonce: nonce,
214
+ metadata: byteEncoder.encode('0x')
215
+ });
216
+ serialized = serialize(SolanaNativePaymentSchema, request);
217
+ } else {
218
+ if (!option.contractAddress) {
219
+ throw new Error(`failed request. no contract address for ${option.type} payment type`);
220
+ }
221
+ const request = new SolanaSplPaymentRequest({
222
+ version: byteEncoder.encode(proofVersion),
223
+ chainId: BigInt(chainId),
224
+ verifyingContract: new PublicKey(paymentRails).toBytes(),
225
+ tokenAddress: new PublicKey(option.contractAddress).toBytes(),
226
+ recipient: new PublicKey(recipient).toBytes(),
227
+ amount: BigInt(amount),
228
+ expirationDate: BigInt(getUnixTimestamp(expirationDate)),
229
+ nonce: nonce,
230
+ metadata: byteEncoder.encode('0x')
231
+ });
232
+ serialized = serialize(SolanaSplPaymentSchema, request);
233
+ }
234
+ const privateKey = solSigner.secretKey.slice(0, 32);
235
+ const signature = await ed25519.sign(serialized, privateKey);
236
+ const proof: Iden3SolanaEd25519SignatureV1[] = [
237
+ {
238
+ type: SupportedPaymentProofType.SolanaEd25519Signature2025,
239
+ proofPurpose: 'assertionMethod',
240
+ proofValue: Buffer.from(signature).toString('hex'),
241
+ created: new Date().toISOString(),
242
+ verificationMethod: `did:pkh:solana:${chainRef}:${solSigner.publicKey.toBase58()}`,
243
+ domain: {
244
+ version: proofVersion,
245
+ chainId,
246
+ verifyingContract: paymentRails
247
+ }
248
+ }
249
+ ];
250
+ const d: Iden3PaymentRailsSolanaRequestV1 = {
251
+ type: PaymentRequestDataType.Iden3PaymentRailsSolanaRequestV1,
252
+ '@context': [
253
+ `https://schema.iden3.io/core/jsonld/payment.jsonld#${option.type}`,
254
+ 'https://schema.iden3.io/core/jsonld/solanaEd25519.jsonld'
255
+ ],
256
+ recipient,
257
+ amount: amount.toString(),
258
+ expirationDate: expirationDate.toISOString(),
259
+ nonce: nonce.toString(),
260
+ metadata: '0x',
261
+ proof
262
+ };
263
+ if (option.type === PaymentRequestDataType.Iden3PaymentRailsSolanaRequestV1) {
264
+ return d;
265
+ }
266
+
267
+ return {
268
+ ...d,
269
+ type: option.type,
270
+ tokenAddress: option.contractAddress || '',
271
+ features: option.features || []
272
+ } as Iden3PaymentRailsSolanaSPLRequestV1;
273
+ };
274
+
275
+ export const serializeSolanaPaymentInstruction = (
276
+ data: Iden3PaymentRailsSolanaRequestV1 | Iden3PaymentRailsSolanaSPLRequestV1
277
+ ): Uint8Array => {
278
+ let serialized: Uint8Array;
279
+ const proof = Array.isArray(data.proof) ? data.proof[0] : data.proof;
280
+ const proofVersion =
281
+ data.type === PaymentRequestDataType.Iden3PaymentRailsSolanaRequestV1
282
+ ? 'SolanaEd25519NativeV1'
283
+ : 'SolanaEd25519SPLV1';
284
+ if (data.type === PaymentRequestDataType.Iden3PaymentRailsSolanaRequestV1) {
285
+ const request = new SolanaNativePaymentRequest({
286
+ version: byteEncoder.encode(proofVersion),
287
+ chainId: BigInt(proof.domain.chainId),
288
+ verifyingContract: new PublicKey(proof.domain.verifyingContract).toBytes(),
289
+ recipient: new PublicKey(data.recipient).toBytes(),
290
+ amount: BigInt(data.amount),
291
+ expirationDate: BigInt(getUnixTimestamp(new Date(data.expirationDate))),
292
+ nonce: BigInt(data.nonce),
293
+ metadata: byteEncoder.encode('0x')
294
+ });
295
+ serialized = serialize(SolanaNativePaymentSchema, request);
296
+ } else {
297
+ const request = new SolanaSplPaymentRequest({
298
+ version: byteEncoder.encode(proofVersion),
299
+ chainId: BigInt(proof.domain.chainId),
300
+ verifyingContract: new PublicKey(proof.domain.verifyingContract).toBytes(),
301
+ tokenAddress: new PublicKey(data.tokenAddress).toBytes(),
302
+ recipient: new PublicKey(data.recipient).toBytes(),
303
+ amount: BigInt(data.amount),
304
+ expirationDate: BigInt(getUnixTimestamp(new Date(data.expirationDate))),
305
+ nonce: BigInt(data.nonce),
306
+ metadata: byteEncoder.encode('0x')
307
+ });
308
+ serialized = serialize(SolanaSplPaymentSchema, request);
309
+ }
310
+ return serialized;
311
+ };
312
+ export const verifyIden3SolanaPaymentRequest = async (
313
+ data: Iden3PaymentRailsSolanaRequestV1 | Iden3PaymentRailsSolanaSPLRequestV1,
314
+ resolver: Resolvable
315
+ ): Promise<boolean> => {
316
+ const proof = Array.isArray(data.proof) ? data.proof[0] : data.proof;
317
+ let serialized: Uint8Array;
318
+ if (data.type === PaymentRequestDataType.Iden3PaymentRailsSolanaRequestV1) {
319
+ const request = new SolanaNativePaymentRequest({
320
+ version: byteEncoder.encode(proof.domain.version),
321
+ chainId: BigInt(proof.domain.chainId),
322
+ verifyingContract: new PublicKey(proof.domain.verifyingContract).toBytes(),
323
+ recipient: new PublicKey(data.recipient).toBytes(),
324
+ amount: BigInt(data.amount),
325
+ expirationDate: BigInt(getUnixTimestamp(new Date(data.expirationDate))),
326
+ nonce: BigInt(data.nonce),
327
+ metadata: byteEncoder.encode('0x')
328
+ });
329
+ serialized = serialize(SolanaNativePaymentSchema, request);
330
+ } else {
331
+ const request = new SolanaSplPaymentRequest({
332
+ version: byteEncoder.encode(proof.domain.version),
333
+ chainId: BigInt(proof.domain.chainId),
334
+ verifyingContract: new PublicKey(proof.domain.verifyingContract).toBytes(),
335
+ tokenAddress: new PublicKey(data.tokenAddress).toBytes(),
336
+ recipient: new PublicKey(data.recipient).toBytes(),
337
+ amount: BigInt(data.amount),
338
+ expirationDate: BigInt(getUnixTimestamp(new Date(data.expirationDate))),
339
+ nonce: BigInt(data.nonce),
340
+ metadata: byteEncoder.encode('0x')
341
+ });
342
+ serialized = serialize(SolanaSplPaymentSchema, request);
343
+ }
344
+
345
+ const { didDocument } = await resolver.resolve(proof.verificationMethod);
346
+ let publicKeyMultibase;
347
+ if (didDocument?.verificationMethod) {
348
+ for (const verificationMethod of didDocument.verificationMethod) {
349
+ if (verificationMethod.type === 'Ed25519VerificationKey2020') {
350
+ publicKeyMultibase = verificationMethod.publicKeyMultibase;
351
+ }
352
+ }
353
+ }
354
+
355
+ if (!publicKeyMultibase) {
356
+ throw new Error('No Ed25519VerificationKey2020 found in DID document');
357
+ }
358
+
359
+ return ed25519.verify(proof.proofValue, serialized, new PublicKey(publicKeyMultibase).toBytes());
360
+ };
@@ -164,7 +164,9 @@ export enum RefreshServiceType {
164
164
  export enum PaymentRequestDataType {
165
165
  Iden3PaymentRequestCryptoV1 = 'Iden3PaymentRequestCryptoV1',
166
166
  Iden3PaymentRailsRequestV1 = 'Iden3PaymentRailsRequestV1',
167
- Iden3PaymentRailsERC20RequestV1 = 'Iden3PaymentRailsERC20RequestV1'
167
+ Iden3PaymentRailsERC20RequestV1 = 'Iden3PaymentRailsERC20RequestV1',
168
+ Iden3PaymentRailsSolanaRequestV1 = 'Iden3PaymentRailsSolanaRequestV1',
169
+ Iden3PaymentRailsSolanaSPLRequestV1 = 'Iden3PaymentRailsSolanaSPLRequestV1'
168
170
  }
169
171
 
170
172
  /**
@@ -175,7 +177,9 @@ export enum PaymentRequestDataType {
175
177
  export enum PaymentType {
176
178
  Iden3PaymentCryptoV1 = 'Iden3PaymentCryptoV1',
177
179
  Iden3PaymentRailsV1 = 'Iden3PaymentRailsV1',
178
- Iden3PaymentRailsERC20V1 = 'Iden3PaymentRailsERC20V1'
180
+ Iden3PaymentRailsERC20V1 = 'Iden3PaymentRailsERC20V1',
181
+ Iden3PaymentRailsSolanaV1 = 'Iden3PaymentRailsSolanaV1',
182
+ Iden3PaymentRailsSolanaSPLV1 = 'Iden3PaymentRailsSolanaSPLV1'
179
183
  }
180
184
 
181
185
  /**
@@ -184,7 +188,8 @@ export enum PaymentType {
184
188
  * @enum {string}
185
189
  */
186
190
  export enum SupportedPaymentProofType {
187
- EthereumEip712Signature2021 = 'EthereumEip712Signature2021'
191
+ EthereumEip712Signature2021 = 'EthereumEip712Signature2021',
192
+ SolanaEd25519Signature2025 = 'SolanaEd25519Signature2025'
188
193
  }
189
194
 
190
195
  /**
@@ -223,3 +228,12 @@ export enum DisplayMethodType {
223
228
  * Default cache max size for in-memory cache
224
229
  */
225
230
  export const DEFAULT_CACHE_MAX_SIZE = 10_000;
231
+
232
+ /**
233
+ * Solana chain reference
234
+ */
235
+ export const SOLANA_CHAIN_REF = Object.freeze({
236
+ DEVNET: 'EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
237
+ TESTNET: '4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',
238
+ MAINNET: '5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'
239
+ });