@settlemint/sdk-portal 2.2.0-maind07ccd95 → 2.2.0-pr0a1949d3

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/README.md CHANGED
@@ -27,9 +27,19 @@
27
27
  ## Table of Contents
28
28
 
29
29
  - [About](#about)
30
+ - [Examples](#examples)
31
+ - [Deploy contract](#deploy-contract)
32
+ - [Get pending transactions](#get-pending-transactions)
33
+ - [Send transaction using hd wallet](#send-transaction-using-hd-wallet)
30
34
  - [API Reference](#api-reference)
31
35
  - [Functions](#functions)
32
36
  - [createPortalClient()](#createportalclient)
37
+ - [handleWalletVerificationChallenge()](#handlewalletverificationchallenge)
38
+ - [waitForTransactionReceipt()](#waitfortransactionreceipt)
39
+ - [Interfaces](#interfaces)
40
+ - [HandleWalletVerificationChallengeOptions\<Setup\>](#handlewalletverificationchallengeoptionssetup)
41
+ - [Transaction](#transaction)
42
+ - [WaitForTransactionReceiptOptions](#waitfortransactionreceiptoptions)
33
43
  - [Type Aliases](#type-aliases)
34
44
  - [ClientOptions](#clientoptions)
35
45
  - [RequestConfig](#requestconfig)
@@ -43,8 +53,310 @@
43
53
  The SettleMint Smart Contract Portal SDK provides a seamless way to interact with the Smart Contract Portal Middleware API. It enables you to easily interact with your smart contracts using a REST or GraphQL API.
44
54
 
45
55
  The SDK offers a type-safe interface for all Portal API operations, with comprehensive error handling and validation. It integrates smoothly with modern TypeScript applications while providing a simple and intuitive developer experience.
56
+ ## Examples
46
57
 
47
- For detailed information about using the Smart Contract Portal Middleware, check out our [official documentation](https://console.settlemint.com/documentation).
58
+ ### Deploy contract
59
+
60
+ ```ts
61
+ /**
62
+ * This example demonstrates how to deploy a contract using the SettleMint Portal.
63
+ *
64
+ * The process involves:
65
+ * 1. Creating a portal client
66
+ * 2. Deploying a forwarder contract
67
+ * 3. Waiting for the forwarder contract deployment to be finalized
68
+ * 4. Deploying a stablecoin factory contract
69
+ * 5. Getting all contracts and filtering by ABI name
70
+ *
71
+ * This pattern is useful for applications that need to deploy smart contracts
72
+ * in the SettleMint Portal, providing a way to track the progress of blockchain operations.
73
+ */
74
+ import { loadEnv } from "@settlemint/sdk-utils/environment";
75
+ import { createLogger, requestLogger } from "@settlemint/sdk-utils/logging";
76
+ import { getAddress } from "viem";
77
+ import { createPortalClient } from "../portal.js"; // Replace this path with "@settlemint/sdk-portal"
78
+ import { waitForTransactionReceipt } from "../utils/wait-for-transaction-receipt.js";
79
+ import type { introspection } from "./schemas/portal-env.d.ts"; // Replace this path with the generated introspection type
80
+
81
+ const env = await loadEnv(false, false);
82
+ const logger = createLogger();
83
+
84
+ const { client: portalClient, graphql: portalGraphql } = createPortalClient<{
85
+ introspection: introspection;
86
+ disableMasking: true;
87
+ scalars: {
88
+ // Change unknown to the type you are using to store metadata
89
+ JSON: unknown;
90
+ };
91
+ }>(
92
+ {
93
+ instance: env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT!,
94
+ accessToken: env.SETTLEMINT_ACCESS_TOKEN!,
95
+ },
96
+ {
97
+ fetch: requestLogger(logger, "portal", fetch) as typeof fetch,
98
+ },
99
+ );
100
+
101
+ // Replace with the address of your private key which you use to deploy smart contracts
102
+ const FROM = getAddress("0x4B03331cF2db1497ec58CAa4AFD8b93611906960");
103
+
104
+ /**
105
+ * Deploy a forwarder contract
106
+ */
107
+ const deployForwarder = await portalClient.request(
108
+ portalGraphql(`
109
+ mutation DeployContractForwarder($from: String!) {
110
+ DeployContractForwarder(from: $from, gasLimit: "0x3d0900") {
111
+ transactionHash
112
+ }
113
+ }
114
+ `),
115
+ {
116
+ from: FROM,
117
+ },
118
+ );
119
+
120
+ /**
121
+ * Wait for the forwarder contract deployment to be finalized
122
+ */
123
+ const transaction = await waitForTransactionReceipt(deployForwarder.DeployContractForwarder?.transactionHash!, {
124
+ portalGraphqlEndpoint: env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT!,
125
+ accessToken: env.SETTLEMINT_ACCESS_TOKEN!,
126
+ });
127
+
128
+ /**
129
+ * Deploy a stablecoin factory contract
130
+ */
131
+ const deployStableCoinFactory = await portalClient.request(
132
+ portalGraphql(`
133
+ mutation DeployContractStableCoinFactory($from: String!, $constructorArguments: DeployContractStableCoinFactoryInput!) {
134
+ DeployContractStableCoinFactory(from: $from, constructorArguments: $constructorArguments, gasLimit: "0x3d0900") {
135
+ transactionHash
136
+ }
137
+ }
138
+ `),
139
+ {
140
+ from: FROM,
141
+ constructorArguments: {
142
+ forwarder: getAddress(transaction?.receipt.contractAddress!),
143
+ },
144
+ },
145
+ );
146
+
147
+ console.log(deployStableCoinFactory?.DeployContractStableCoinFactory?.transactionHash);
148
+
149
+ const contractAddresses = await portalClient.request(
150
+ portalGraphql(`
151
+ query GetContracts {
152
+ getContracts {
153
+ count
154
+ records {
155
+ address
156
+ abiName
157
+ createdAt
158
+ }
159
+ }
160
+ }
161
+ `),
162
+ );
163
+ // Print total count
164
+ console.log(`Total contracts: ${contractAddresses.getContracts?.count}`);
165
+
166
+ // Contracts for StableCoinFactory
167
+ console.log(contractAddresses.getContracts?.records.filter((record) => record.abiName === "StableCoinFactory"));
168
+
169
+ ```
170
+ ### Get pending transactions
171
+
172
+ ```ts
173
+ /**
174
+ * This example demonstrates how to get the number of pending transactions in the SettleMint Portal.
175
+ *
176
+ * The process involves:
177
+ * 1. Creating a portal client
178
+ * 2. Making a GraphQL query to get the number of pending transactions
179
+ *
180
+ * This pattern is useful for applications that need to monitor the status of pending transactions
181
+ * in the SettleMint Portal, providing a way to track the progress of blockchain operations.
182
+ */
183
+ import { loadEnv } from "@settlemint/sdk-utils/environment";
184
+ import { createLogger, requestLogger } from "@settlemint/sdk-utils/logging";
185
+ import { createPortalClient } from "../portal.js"; // Replace this path with "@settlemint/sdk-portal"
186
+ import type { introspection } from "./schemas/portal-env.d.ts"; // Replace this path with the generated introspection type
187
+
188
+ const env = await loadEnv(false, false);
189
+ const logger = createLogger();
190
+
191
+ const { client: portalClient, graphql: portalGraphql } = createPortalClient<{
192
+ introspection: introspection;
193
+ disableMasking: true;
194
+ scalars: {
195
+ // Change unknown to the type you are using to store metadata
196
+ JSON: unknown;
197
+ };
198
+ }>(
199
+ {
200
+ instance: env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT!,
201
+ accessToken: env.SETTLEMINT_ACCESS_TOKEN!,
202
+ },
203
+ {
204
+ fetch: requestLogger(logger, "portal", fetch) as typeof fetch,
205
+ },
206
+ );
207
+
208
+ // Making GraphQL queries
209
+ const query = portalGraphql(`
210
+ query GetPendingTransactions {
211
+ getPendingTransactions {
212
+ count
213
+ }
214
+ }
215
+ `);
216
+
217
+ const result = await portalClient.request(query);
218
+ console.log(`There are ${result.getPendingTransactions?.count} pending transactions`);
219
+
220
+ ```
221
+ ### Send transaction using hd wallet
222
+
223
+ ```ts
224
+ /**
225
+ * This example demonstrates how to send a transaction using an HD wallet in the SettleMint Portal.
226
+ *
227
+ * The process involves:
228
+ * 1. Creating a wallet for a user using the HD private key
229
+ * 2. Setting up a pincode for wallet verification
230
+ * 3. Handling the wallet verification challenge
231
+ * 4. Sending a transaction to the blockchain
232
+ *
233
+ * This pattern is useful for applications that need to manage multiple user wallets
234
+ * derived from a single HD wallet, providing a secure and scalable approach to
235
+ * blockchain interactions in enterprise applications.
236
+ */
237
+ import { loadEnv } from "@settlemint/sdk-utils/environment";
238
+ import { createLogger, requestLogger } from "@settlemint/sdk-utils/logging";
239
+ import type { Address } from "viem";
240
+ import { createPortalClient } from "../portal.js"; // Replace this path with "@settlemint/sdk-portal"
241
+ import { handleWalletVerificationChallenge } from "../utils/wallet-verification-challenge.js"; // Replace this path with "@settlemint/sdk-portal"
242
+ import type { introspection } from "./schemas/portal-env.js"; // Replace this path with the generated introspection type
243
+
244
+ const env = await loadEnv(false, false);
245
+ const logger = createLogger();
246
+
247
+ const { client: portalClient, graphql: portalGraphql } = createPortalClient<{
248
+ introspection: introspection;
249
+ disableMasking: true;
250
+ scalars: {
251
+ // Change unknown to the type you are using to store metadata
252
+ JSON: unknown;
253
+ };
254
+ }>(
255
+ {
256
+ instance: env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT!,
257
+ accessToken: env.SETTLEMINT_ACCESS_TOKEN!,
258
+ },
259
+ {
260
+ fetch: requestLogger(logger, "portal", fetch) as typeof fetch,
261
+ },
262
+ );
263
+
264
+ /**
265
+ * First create a wallet using the HD private key, this needs to be done for every user that is using your app
266
+ */
267
+ const wallet = await portalClient.request(
268
+ portalGraphql(`
269
+ mutation createUserWallet($keyVaultId: String!, $name: String!) {
270
+ createWallet(keyVaultId: $keyVaultId, walletInfo: { name: $name }) {
271
+ address
272
+ }
273
+ }
274
+ `),
275
+ {
276
+ keyVaultId: env.SETTLEMINT_HD_PRIVATE_KEY!,
277
+ name: "My Wallet",
278
+ },
279
+ );
280
+
281
+ /**
282
+ * Set a pincode for the wallet, this is used to verify the wallet when the user is sending a transaction to the chain
283
+ */
284
+ const pincodeVerification = await portalClient.request(
285
+ portalGraphql(`
286
+ mutation setPinCode($address: String!, $pincode: String!) {
287
+ createWalletVerification(
288
+ userWalletAddress: $address
289
+ verificationInfo: {pincode: {name: "PINCODE", pincode: $pincode}}
290
+ ) {
291
+ id
292
+ name
293
+ parameters
294
+ verificationType
295
+ }
296
+ }
297
+ `),
298
+ {
299
+ address: wallet.createWallet?.address!,
300
+ pincode: "123456",
301
+ },
302
+ );
303
+
304
+ /**
305
+ * Generate a challenge response for the pincode verification
306
+ */
307
+ const challengeResponse = await handleWalletVerificationChallenge({
308
+ portalClient,
309
+ portalGraphql,
310
+ verificationId: pincodeVerification.createWalletVerification?.id!,
311
+ userWalletAddress: wallet.createWallet?.address! as Address,
312
+ code: "123456",
313
+ verificationType: "pincode",
314
+ });
315
+
316
+ /**
317
+ * Send a transaction to the chain
318
+ * This is a sample of how to send a transaction to the chain using the portal client and the asset tokenization kit
319
+ * The challenge response is generated using the handleWalletVerificationChallenge function, this is used to verifiy wallet access
320
+ * @see https://github.com/settlemint/asset-tokenization-kit
321
+ */
322
+ const result = await portalClient.request(
323
+ portalGraphql(`
324
+ mutation StableCoinFactoryCreate(
325
+ $challengeResponse: String!
326
+ $verificationId: String
327
+ $address: String!
328
+ $from: String!
329
+ $input: StableCoinFactoryCreateInput!
330
+ ) {
331
+ StableCoinFactoryCreate(
332
+ challengeResponse: $challengeResponse
333
+ verificationId: $verificationId
334
+ address: $address
335
+ from: $from
336
+ input: $input
337
+ ) {
338
+ transactionHash
339
+ }
340
+ }
341
+ `),
342
+ {
343
+ challengeResponse: challengeResponse.challengeResponse,
344
+ verificationId: pincodeVerification.createWalletVerification?.id!,
345
+ address: "0x5e771e1417100000000000000000000000000004",
346
+ from: wallet.createWallet?.address!,
347
+ input: {
348
+ name: "Test Coin",
349
+ symbol: "TEST",
350
+ decimals: 18,
351
+ collateralLivenessSeconds: 3_600,
352
+ },
353
+ },
354
+ );
355
+
356
+ // Log the transaction hash
357
+ console.log("Transaction hash:", result.StableCoinFactoryCreate?.transactionHash);
358
+
359
+ ```
48
360
 
49
361
  ## API Reference
50
362
 
@@ -54,7 +366,7 @@ For detailed information about using the Smart Contract Portal Middleware, check
54
366
 
55
367
  > **createPortalClient**\<`Setup`\>(`options`, `clientOptions?`): `object`
56
368
 
57
- Defined in: [sdk/portal/src/portal.ts:66](https://github.com/settlemint/sdk/blob/v2.2.0/sdk/portal/src/portal.ts#L66)
369
+ Defined in: [sdk/portal/src/portal.ts:71](https://github.com/settlemint/sdk/blob/v2.2.0/sdk/portal/src/portal.ts#L71)
58
370
 
59
371
  Creates a Portal GraphQL client with the provided configuration.
60
372
 
@@ -82,8 +394,8 @@ An object containing the configured GraphQL client and graphql helper function
82
394
 
83
395
  | Name | Type | Defined in |
84
396
  | ------ | ------ | ------ |
85
- | `client` | `GraphQLClient` | [sdk/portal/src/portal.ts:70](https://github.com/settlemint/sdk/blob/v2.2.0/sdk/portal/src/portal.ts#L70) |
86
- | `graphql` | `initGraphQLTada`\<`Setup`\> | [sdk/portal/src/portal.ts:71](https://github.com/settlemint/sdk/blob/v2.2.0/sdk/portal/src/portal.ts#L71) |
397
+ | `client` | `GraphQLClient` | [sdk/portal/src/portal.ts:75](https://github.com/settlemint/sdk/blob/v2.2.0/sdk/portal/src/portal.ts#L75) |
398
+ | `graphql` | `initGraphQLTada`\<`Setup`\> | [sdk/portal/src/portal.ts:76](https://github.com/settlemint/sdk/blob/v2.2.0/sdk/portal/src/portal.ts#L76) |
87
399
 
88
400
  ##### Throws
89
401
 
@@ -92,28 +404,33 @@ If the provided options fail validation
92
404
  ##### Example
93
405
 
94
406
  ```ts
95
- import { createPortalClient } from '@settlemint/sdk-portal';
407
+ import { createPortalClient } from "@settlemint/sdk-portal";
408
+ import { loadEnv } from "@settlemint/sdk-utils/environment";
409
+ import { createLogger, requestLogger } from "@settlemint/sdk-utils/logging";
96
410
  import type { introspection } from "@schemas/portal-env";
97
- import { createLogger, requestLogger } from '@settlemint/sdk-utils/logging';
98
411
 
412
+ const env = await loadEnv(false, false);
99
413
  const logger = createLogger();
100
414
 
101
- export const { client: portalClient, graphql: portalGraphql } = createPortalClient<{
415
+ const { client: portalClient, graphql: portalGraphql } = createPortalClient<{
102
416
  introspection: introspection;
103
417
  disableMasking: true;
104
418
  scalars: {
105
419
  // Change unknown to the type you are using to store metadata
106
420
  JSON: unknown;
107
421
  };
108
- }>({
109
- instance: process.env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT,
110
- accessToken: process.env.SETTLEMINT_ACCESS_TOKEN,
111
- }, {
112
- fetch: requestLogger(logger, "portal", fetch) as typeof fetch,
113
- });
422
+ }>(
423
+ {
424
+ instance: env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT!,
425
+ accessToken: env.SETTLEMINT_ACCESS_TOKEN!,
426
+ },
427
+ {
428
+ fetch: requestLogger(logger, "portal", fetch) as typeof fetch,
429
+ },
430
+ );
114
431
 
115
432
  // Making GraphQL queries
116
- const query = graphql(`
433
+ const query = portalGraphql(`
117
434
  query GetPendingTransactions {
118
435
  getPendingTransactions {
119
436
  count
@@ -121,9 +438,132 @@ const query = graphql(`
121
438
  }
122
439
  `);
123
440
 
124
- const result = await client.request(query);
441
+ const result = await portalClient.request(query);
442
+ ```
443
+
444
+ ***
445
+
446
+ #### handleWalletVerificationChallenge()
447
+
448
+ > **handleWalletVerificationChallenge**\<`Setup`\>(`options`): `Promise`\<\{ `challengeResponse`: `string`; `verificationId?`: `string`; \}\>
449
+
450
+ Defined in: [sdk/portal/src/utils/wallet-verification-challenge.ts:106](https://github.com/settlemint/sdk/blob/v2.2.0/sdk/portal/src/utils/wallet-verification-challenge.ts#L106)
451
+
452
+ Handles a wallet verification challenge by generating an appropriate response
453
+
454
+ ##### Type Parameters
455
+
456
+ | Type Parameter |
457
+ | ------ |
458
+ | `Setup` *extends* `AbstractSetupSchema` |
459
+
460
+ ##### Parameters
461
+
462
+ | Parameter | Type | Description |
463
+ | ------ | ------ | ------ |
464
+ | `options` | [`HandleWalletVerificationChallengeOptions`](#handlewalletverificationchallengeoptions)\<`Setup`\> | The options for handling the wallet verification challenge |
465
+
466
+ ##### Returns
467
+
468
+ `Promise`\<\{ `challengeResponse`: `string`; `verificationId?`: `string`; \}\>
469
+
470
+ Promise resolving to an object containing the challenge response and optionally the verification ID
471
+
472
+ ##### Throws
473
+
474
+ If the challenge cannot be created or is invalid
475
+
476
+ ##### Example
477
+
478
+ ```ts
479
+ import { createPortalClient } from "@settlemint/sdk-portal";
480
+ import { handleWalletVerificationChallenge } from "@settlemint/sdk-portal";
481
+
482
+ const { client, graphql } = createPortalClient({
483
+ instance: "https://portal.example.com/graphql",
484
+ accessToken: "your-access-token"
485
+ });
486
+
487
+ const result = await handleWalletVerificationChallenge({
488
+ portalClient: client,
489
+ portalGraphql: graphql,
490
+ verificationId: "verification-123",
491
+ userWalletAddress: "0x123...",
492
+ code: "123456",
493
+ verificationType: "otp"
494
+ });
495
+ ```
496
+
497
+ ***
498
+
499
+ #### waitForTransactionReceipt()
500
+
501
+ > **waitForTransactionReceipt**(`transactionHash`, `options`): `Promise`\<[`Transaction`](#transaction)\>
502
+
503
+ Defined in: [sdk/portal/src/utils/wait-for-transaction-receipt.ts:82](https://github.com/settlemint/sdk/blob/v2.2.0/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L82)
504
+
505
+ Waits for a blockchain transaction receipt by subscribing to transaction updates via GraphQL.
506
+ This function polls until the transaction is confirmed or the timeout is reached.
507
+
508
+ ##### Parameters
509
+
510
+ | Parameter | Type | Description |
511
+ | ------ | ------ | ------ |
512
+ | `transactionHash` | `string` | The hash of the transaction to wait for |
513
+ | `options` | [`WaitForTransactionReceiptOptions`](#waitfortransactionreceiptoptions) | Configuration options for the waiting process |
514
+
515
+ ##### Returns
516
+
517
+ `Promise`\<[`Transaction`](#transaction)\>
518
+
519
+ The transaction details including receipt information when the transaction is confirmed
520
+
521
+ ##### Throws
522
+
523
+ Error if the transaction receipt cannot be retrieved within the specified timeout
524
+
525
+ ##### Example
526
+
527
+ ```ts
528
+ import { waitForTransactionReceipt } from "@settlemint/sdk-portal";
529
+
530
+ const transaction = await waitForTransactionReceipt("0x123...", {
531
+ portalGraphqlEndpoint: "https://example.settlemint.com/graphql",
532
+ accessToken: "your-access-token",
533
+ timeout: 30000 // 30 seconds timeout
534
+ });
125
535
  ```
126
536
 
537
+ ### Interfaces
538
+
539
+ #### HandleWalletVerificationChallengeOptions\<Setup\>
540
+
541
+ Defined in: [sdk/portal/src/utils/wallet-verification-challenge.ts:73](https://github.com/settlemint/sdk/blob/v2.2.0/sdk/portal/src/utils/wallet-verification-challenge.ts#L73)
542
+
543
+ Options for handling a wallet verification challenge
544
+
545
+ ##### Type Parameters
546
+
547
+ | Type Parameter | Description |
548
+ | ------ | ------ |
549
+ | `Setup` *extends* `AbstractSetupSchema` | The GraphQL schema setup type |
550
+
551
+ ***
552
+
553
+ #### Transaction
554
+
555
+ Defined in: [sdk/portal/src/utils/wait-for-transaction-receipt.ts:25](https://github.com/settlemint/sdk/blob/v2.2.0/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L25)
556
+
557
+ Represents the structure of a blockchain transaction with its receipt
558
+
559
+ ***
560
+
561
+ #### WaitForTransactionReceiptOptions
562
+
563
+ Defined in: [sdk/portal/src/utils/wait-for-transaction-receipt.ts:58](https://github.com/settlemint/sdk/blob/v2.2.0/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L58)
564
+
565
+ Options for waiting for a transaction receipt
566
+
127
567
  ### Type Aliases
128
568
 
129
569
  #### ClientOptions
package/dist/portal.cjs CHANGED
@@ -22,7 +22,9 @@ var portal_exports = {};
22
22
  __export(portal_exports, {
23
23
  ClientOptionsSchema: () => ClientOptionsSchema,
24
24
  createPortalClient: () => createPortalClient,
25
- readFragment: () => import_gql2.readFragment
25
+ handleWalletVerificationChallenge: () => handleWalletVerificationChallenge,
26
+ readFragment: () => import_gql2.readFragment,
27
+ waitForTransactionReceipt: () => waitForTransactionReceipt
26
28
  });
27
29
  module.exports = __toCommonJS(portal_exports);
28
30
  var import_runtime = require("@settlemint/sdk-utils/runtime");
@@ -30,6 +32,137 @@ var import_validation = require("@settlemint/sdk-utils/validation");
30
32
  var import_gql = require("gql.tada");
31
33
  var import_graphql_request = require("graphql-request");
32
34
  var import_zod = require("zod");
35
+
36
+ // src/utils/wallet-verification-challenge.ts
37
+ var import_node_crypto = require("crypto");
38
+ var ChallengeError = class extends Error {
39
+ code;
40
+ constructor(message, code) {
41
+ super(message);
42
+ this.name = "ChallengeError";
43
+ this.code = code;
44
+ }
45
+ };
46
+ function hashPincode(pincode, salt) {
47
+ return (0, import_node_crypto.createHash)("sha256").update(`${salt}${pincode}`).digest("hex");
48
+ }
49
+ function generateResponse(pincode, salt, challenge) {
50
+ const hashedPincode = hashPincode(pincode, salt);
51
+ return (0, import_node_crypto.createHash)("sha256").update(`${hashedPincode}_${challenge}`).digest("hex");
52
+ }
53
+ async function handleWalletVerificationChallenge({
54
+ portalClient,
55
+ portalGraphql,
56
+ verificationId,
57
+ userWalletAddress,
58
+ code,
59
+ verificationType
60
+ }) {
61
+ try {
62
+ if (verificationType === "otp") {
63
+ return {
64
+ challengeResponse: code.toString(),
65
+ verificationId
66
+ };
67
+ }
68
+ if (verificationType === "secret-code") {
69
+ const formattedCode = code.toString().replace(/(.{5})(?=.)/, "$1-");
70
+ return {
71
+ challengeResponse: formattedCode,
72
+ verificationId
73
+ };
74
+ }
75
+ const verificationChallenges = await portalClient.request(
76
+ portalGraphql(`
77
+ mutation CreateWalletVerificationChallenges($userWalletAddress: String!, $verificationId: String!) {
78
+ createWalletVerificationChallenges(userWalletAddress: $userWalletAddress, verificationId: $verificationId) {
79
+ challenge
80
+ id
81
+ name
82
+ verificationType
83
+ }
84
+ }
85
+ `),
86
+ {
87
+ userWalletAddress,
88
+ verificationId
89
+ }
90
+ );
91
+ if (!verificationChallenges.createWalletVerificationChallenges?.length) {
92
+ throw new ChallengeError("No verification challenges received", "NO_CHALLENGES");
93
+ }
94
+ const walletVerificationChallenge = verificationChallenges.createWalletVerificationChallenges.find(
95
+ (challenge) => challenge.id === verificationId
96
+ );
97
+ if (!walletVerificationChallenge?.challenge?.secret || !walletVerificationChallenge?.challenge?.salt) {
98
+ throw new ChallengeError("Invalid challenge format", "INVALID_CHALLENGE");
99
+ }
100
+ const { secret, salt } = walletVerificationChallenge.challenge;
101
+ const challengeResponse = generateResponse(code.toString(), salt, secret);
102
+ return {
103
+ challengeResponse,
104
+ verificationId
105
+ };
106
+ } catch (error) {
107
+ if (error instanceof ChallengeError) {
108
+ throw error;
109
+ }
110
+ throw new ChallengeError("Failed to process wallet verification challenge", "CHALLENGE_PROCESSING_ERROR");
111
+ }
112
+ }
113
+
114
+ // src/utils/wait-for-transaction-receipt.ts
115
+ var import_graphql_ws = require("graphql-ws");
116
+ async function waitForTransactionReceipt(transactionHash, options) {
117
+ const wsClient = (0, import_graphql_ws.createClient)({
118
+ url: options.portalGraphqlEndpoint.toLowerCase().replace("/graphql", `/${options.accessToken}/graphql`)
119
+ });
120
+ const subscription = wsClient.iterate({
121
+ query: `subscription getTransaction($transactionHash: String!) {
122
+ getTransaction(transactionHash: $transactionHash) {
123
+ receipt {
124
+ transactionHash
125
+ to
126
+ status
127
+ from
128
+ type
129
+ revertReason
130
+ revertReasonDecoded
131
+ logs
132
+ events
133
+ contractAddress
134
+ }
135
+ transactionHash
136
+ from
137
+ createdAt
138
+ address
139
+ functionName
140
+ isContract
141
+ }
142
+ }`,
143
+ variables: { transactionHash }
144
+ });
145
+ const promises = [getTransactionFromSubscription(subscription)];
146
+ if (options.timeout) {
147
+ promises.push(createTimeoutPromise(options.timeout));
148
+ }
149
+ return Promise.race(promises);
150
+ }
151
+ function createTimeoutPromise(timeout) {
152
+ return new Promise((_, reject) => {
153
+ setTimeout(() => reject(new Error("Transaction receipt not found")), timeout);
154
+ });
155
+ }
156
+ async function getTransactionFromSubscription(subscription) {
157
+ for await (const result of subscription) {
158
+ if (result?.data?.getTransaction?.receipt) {
159
+ return result.data.getTransaction;
160
+ }
161
+ }
162
+ throw new Error("No transaction found");
163
+ }
164
+
165
+ // src/portal.ts
33
166
  var import_gql2 = require("gql.tada");
34
167
  var ClientOptionsSchema = import_zod.z.object({
35
168
  instance: import_validation.UrlOrPathSchema,
@@ -53,6 +186,8 @@ function createPortalClient(options, clientOptions) {
53
186
  0 && (module.exports = {
54
187
  ClientOptionsSchema,
55
188
  createPortalClient,
56
- readFragment
189
+ handleWalletVerificationChallenge,
190
+ readFragment,
191
+ waitForTransactionReceipt
57
192
  });
58
193
  //# sourceMappingURL=portal.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/portal.ts"],"sourcesContent":["import { ensureServer } from \"@settlemint/sdk-utils/runtime\";\nimport { ApplicationAccessTokenSchema, UrlOrPathSchema, validate } from \"@settlemint/sdk-utils/validation\";\nimport { type AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport { GraphQLClient } from \"graphql-request\";\nimport { z } from \"zod\";\n\n/**\n * Configuration options for the GraphQL client, excluding 'url' and 'exchanges'.\n */\nexport type RequestConfig = ConstructorParameters<typeof GraphQLClient>[1];\n\n/**\n * Schema for validating Portal client configuration options.\n */\nexport const ClientOptionsSchema = z.object({\n instance: UrlOrPathSchema,\n accessToken: ApplicationAccessTokenSchema,\n cache: z.enum([\"default\", \"force-cache\", \"no-cache\", \"no-store\", \"only-if-cached\", \"reload\"]).optional(),\n});\n\n/**\n * Type representing the validated client options.\n */\nexport type ClientOptions = z.infer<typeof ClientOptionsSchema>;\n\n/**\n * Creates a Portal GraphQL client with the provided configuration.\n *\n * @param options - Configuration options for the Portal client\n * @param clientOptions - Additional GraphQL client configuration options\n * @returns An object containing the configured GraphQL client and graphql helper function\n * @throws If the provided options fail validation\n *\n * @example\n * import { createPortalClient } from '@settlemint/sdk-portal';\n * import type { introspection } from \"@schemas/portal-env\";\n * import { createLogger, requestLogger } from '@settlemint/sdk-utils/logging';\n *\n * const logger = createLogger();\n *\n * export const { client: portalClient, graphql: portalGraphql } = createPortalClient<{\n * introspection: introspection;\n * disableMasking: true;\n * scalars: {\n * // Change unknown to the type you are using to store metadata\n * JSON: unknown;\n * };\n * }>({\n * instance: process.env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT,\n * accessToken: process.env.SETTLEMINT_ACCESS_TOKEN,\n * }, {\n * fetch: requestLogger(logger, \"portal\", fetch) as typeof fetch,\n * });\n *\n * // Making GraphQL queries\n * const query = graphql(`\n * query GetPendingTransactions {\n * getPendingTransactions {\n * count\n * }\n * }\n * `);\n *\n * const result = await client.request(query);\n */\nexport function createPortalClient<const Setup extends AbstractSetupSchema>(\n options: ClientOptions,\n clientOptions?: RequestConfig,\n): {\n client: GraphQLClient;\n graphql: initGraphQLTada<Setup>;\n} {\n ensureServer();\n const validatedOptions = validate(ClientOptionsSchema, options);\n const graphql = initGraphQLTada<Setup>();\n const fullUrl = new URL(validatedOptions.instance).toString();\n\n return {\n client: new GraphQLClient(fullUrl, {\n ...clientOptions,\n headers: { ...(clientOptions?.headers ?? {}), \"x-auth-token\": validatedOptions.accessToken },\n }),\n graphql,\n };\n}\n\nexport { readFragment } from \"gql.tada\";\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA6B;AAC7B,wBAAwE;AACxE,iBAA0D;AAC1D,6BAA8B;AAC9B,iBAAkB;AAkFlB,IAAAA,cAA6B;AAxEtB,IAAM,sBAAsB,aAAE,OAAO;AAAA,EAC1C,UAAU;AAAA,EACV,aAAa;AAAA,EACb,OAAO,aAAE,KAAK,CAAC,WAAW,eAAe,YAAY,YAAY,kBAAkB,QAAQ,CAAC,EAAE,SAAS;AACzG,CAAC;AA+CM,SAAS,mBACd,SACA,eAIA;AACA,mCAAa;AACb,QAAM,uBAAmB,4BAAS,qBAAqB,OAAO;AAC9D,QAAM,cAAU,4BAAuB;AACvC,QAAM,UAAU,IAAI,IAAI,iBAAiB,QAAQ,EAAE,SAAS;AAE5D,SAAO;AAAA,IACL,QAAQ,IAAI,qCAAc,SAAS;AAAA,MACjC,GAAG;AAAA,MACH,SAAS,EAAE,GAAI,eAAe,WAAW,CAAC,GAAI,gBAAgB,iBAAiB,YAAY;AAAA,IAC7F,CAAC;AAAA,IACD;AAAA,EACF;AACF;","names":["import_gql"]}
1
+ {"version":3,"sources":["../src/portal.ts","../src/utils/wallet-verification-challenge.ts","../src/utils/wait-for-transaction-receipt.ts"],"sourcesContent":["import { ensureServer } from \"@settlemint/sdk-utils/runtime\";\nimport { ApplicationAccessTokenSchema, UrlOrPathSchema, validate } from \"@settlemint/sdk-utils/validation\";\nimport { type AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport { GraphQLClient } from \"graphql-request\";\nimport { z } from \"zod\";\n\n/**\n * Configuration options for the GraphQL client, excluding 'url' and 'exchanges'.\n */\nexport type RequestConfig = ConstructorParameters<typeof GraphQLClient>[1];\n\n/**\n * Schema for validating Portal client configuration options.\n */\nexport const ClientOptionsSchema = z.object({\n instance: UrlOrPathSchema,\n accessToken: ApplicationAccessTokenSchema,\n cache: z.enum([\"default\", \"force-cache\", \"no-cache\", \"no-store\", \"only-if-cached\", \"reload\"]).optional(),\n});\n\n/**\n * Type representing the validated client options.\n */\nexport type ClientOptions = z.infer<typeof ClientOptionsSchema>;\n\n/**\n * Creates a Portal GraphQL client with the provided configuration.\n *\n * @param options - Configuration options for the Portal client\n * @param clientOptions - Additional GraphQL client configuration options\n * @returns An object containing the configured GraphQL client and graphql helper function\n * @throws If the provided options fail validation\n *\n * @example\n * import { createPortalClient } from \"@settlemint/sdk-portal\";\n * import { loadEnv } from \"@settlemint/sdk-utils/environment\";\n * import { createLogger, requestLogger } from \"@settlemint/sdk-utils/logging\";\n * import type { introspection } from \"@schemas/portal-env\";\n *\n * const env = await loadEnv(false, false);\n * const logger = createLogger();\n *\n * const { client: portalClient, graphql: portalGraphql } = createPortalClient<{\n * introspection: introspection;\n * disableMasking: true;\n * scalars: {\n * // Change unknown to the type you are using to store metadata\n * JSON: unknown;\n * };\n * }>(\n * {\n * instance: env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT!,\n * accessToken: env.SETTLEMINT_ACCESS_TOKEN!,\n * },\n * {\n * fetch: requestLogger(logger, \"portal\", fetch) as typeof fetch,\n * },\n * );\n *\n * // Making GraphQL queries\n * const query = portalGraphql(`\n * query GetPendingTransactions {\n * getPendingTransactions {\n * count\n * }\n * }\n * `);\n *\n * const result = await portalClient.request(query);\n */\nexport function createPortalClient<const Setup extends AbstractSetupSchema>(\n options: ClientOptions,\n clientOptions?: RequestConfig,\n): {\n client: GraphQLClient;\n graphql: initGraphQLTada<Setup>;\n} {\n ensureServer();\n const validatedOptions = validate(ClientOptionsSchema, options);\n const graphql = initGraphQLTada<Setup>();\n const fullUrl = new URL(validatedOptions.instance).toString();\n\n return {\n client: new GraphQLClient(fullUrl, {\n ...clientOptions,\n headers: { ...(clientOptions?.headers ?? {}), \"x-auth-token\": validatedOptions.accessToken },\n }),\n graphql,\n };\n}\n\nexport {\n handleWalletVerificationChallenge,\n type HandleWalletVerificationChallengeOptions,\n} from \"./utils/wallet-verification-challenge.js\";\nexport {\n waitForTransactionReceipt,\n type Transaction,\n type WaitForTransactionReceiptOptions,\n} from \"./utils/wait-for-transaction-receipt.js\";\nexport { readFragment } from \"gql.tada\";\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\n","import { createHash } from \"node:crypto\";\nimport type { AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport type { GraphQLClient } from \"graphql-request\";\nimport type { Address } from \"viem\";\n\n/**\n * Custom error class for challenge-related errors\n */\nexport class ChallengeError extends Error {\n readonly code: string;\n\n constructor(message: string, code: string) {\n super(message);\n this.name = \"ChallengeError\";\n this.code = code;\n }\n}\n\n/**\n * Represents the structure of a wallet verification challenge\n */\ninterface WalletVerificationChallenge {\n challenge: {\n secret: string;\n salt: string;\n };\n id: string;\n name: string;\n verificationType: string;\n}\n\n/**\n * Response type for the CreateWalletVerificationChallenges mutation\n */\ninterface CreateWalletVerificationChallengesResponse {\n createWalletVerificationChallenges: WalletVerificationChallenge[];\n}\n\n/**\n * Hashes a pincode with a salt using SHA-256\n * @param pincode - The pincode to hash\n * @param salt - The salt to use in hashing\n * @returns The hashed pincode as a hex string\n */\nfunction hashPincode(pincode: string, salt: string): string {\n return createHash(\"sha256\").update(`${salt}${pincode}`).digest(\"hex\");\n}\n\n/**\n * Generates a challenge response by combining a hashed pincode with a challenge\n * @param pincode - The user's pincode\n * @param salt - The salt provided in the challenge\n * @param challenge - The challenge secret\n * @returns The challenge response as a hex string\n */\nfunction generateResponse(pincode: string, salt: string, challenge: string): string {\n const hashedPincode = hashPincode(pincode, salt);\n return createHash(\"sha256\").update(`${hashedPincode}_${challenge}`).digest(\"hex\");\n}\n\n/**\n * Options for handling a wallet verification challenge\n *\n * @typedef {Object} HandleWalletVerificationChallengeOptions\n * @template {AbstractSetupSchema} Setup - The GraphQL schema setup type\n * @property {GraphQLClient} portalClient - The portal client instance\n * @property {initGraphQLTada<Setup>} portalGraphql - The GraphQL query builder\n * @property {string} verificationId - The ID of the verification challenge\n * @property {Address} userWalletAddress - The wallet address to verify\n * @property {string | number} code - The verification code provided by the user\n * @property {\"otp\" | \"secret-code\" | \"pincode\"} verificationType - The type of verification being performed\n */\nexport interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSchema> {\n portalClient: GraphQLClient;\n portalGraphql: initGraphQLTada<Setup>;\n verificationId: string;\n userWalletAddress: Address;\n code: string | number;\n verificationType: \"otp\" | \"secret-code\" | \"pincode\";\n}\n\n/**\n * Handles a wallet verification challenge by generating an appropriate response\n *\n * @param options - The options for handling the wallet verification challenge\n * @returns Promise resolving to an object containing the challenge response and optionally the verification ID\n * @throws {ChallengeError} If the challenge cannot be created or is invalid\n * @example\n * import { createPortalClient } from \"@settlemint/sdk-portal\";\n * import { handleWalletVerificationChallenge } from \"@settlemint/sdk-portal\";\n *\n * const { client, graphql } = createPortalClient({\n * instance: \"https://portal.example.com/graphql\",\n * accessToken: \"your-access-token\"\n * });\n *\n * const result = await handleWalletVerificationChallenge({\n * portalClient: client,\n * portalGraphql: graphql,\n * verificationId: \"verification-123\",\n * userWalletAddress: \"0x123...\",\n * code: \"123456\",\n * verificationType: \"otp\"\n * });\n */\nexport async function handleWalletVerificationChallenge<const Setup extends AbstractSetupSchema>({\n portalClient,\n portalGraphql,\n verificationId,\n userWalletAddress,\n code,\n verificationType,\n}: HandleWalletVerificationChallengeOptions<Setup>): Promise<{\n challengeResponse: string;\n verificationId?: string;\n}> {\n try {\n if (verificationType === \"otp\") {\n return {\n challengeResponse: code.toString(),\n verificationId,\n };\n }\n\n if (verificationType === \"secret-code\") {\n // Add - separator to the code\n const formattedCode = code.toString().replace(/(.{5})(?=.)/, \"$1-\");\n return {\n challengeResponse: formattedCode,\n verificationId,\n };\n }\n\n const verificationChallenges = await portalClient.request<CreateWalletVerificationChallengesResponse>(\n portalGraphql(`\n mutation CreateWalletVerificationChallenges($userWalletAddress: String!, $verificationId: String!) {\n createWalletVerificationChallenges(userWalletAddress: $userWalletAddress, verificationId: $verificationId) {\n challenge\n id\n name\n verificationType\n }\n }\n `),\n {\n userWalletAddress,\n verificationId,\n },\n );\n\n if (!verificationChallenges.createWalletVerificationChallenges?.length) {\n throw new ChallengeError(\"No verification challenges received\", \"NO_CHALLENGES\");\n }\n\n const walletVerificationChallenge = verificationChallenges.createWalletVerificationChallenges.find(\n (challenge) => challenge.id === verificationId,\n );\n\n if (!walletVerificationChallenge?.challenge?.secret || !walletVerificationChallenge?.challenge?.salt) {\n throw new ChallengeError(\"Invalid challenge format\", \"INVALID_CHALLENGE\");\n }\n\n const { secret, salt } = walletVerificationChallenge.challenge;\n const challengeResponse = generateResponse(code.toString(), salt, secret);\n return {\n challengeResponse,\n verificationId,\n };\n } catch (error) {\n if (error instanceof ChallengeError) {\n throw error;\n }\n throw new ChallengeError(\"Failed to process wallet verification challenge\", \"CHALLENGE_PROCESSING_ERROR\");\n }\n}\n","import { type FormattedExecutionResult, createClient } from \"graphql-ws\";\n\n/**\n * Represents the structure of a blockchain transaction with its receipt\n *\n * @typedef {Object} Transaction\n * @property {Object} receipt - The transaction receipt details\n * @property {string} receipt.transactionHash - The hash of the transaction\n * @property {string} receipt.to - The recipient address of the transaction\n * @property {string} receipt.status - The status of the transaction (success/failure)\n * @property {string} receipt.from - The sender address of the transaction\n * @property {string} receipt.type - The type of the transaction\n * @property {string} receipt.revertReason - The reason for transaction reversion, if applicable\n * @property {string} receipt.revertReasonDecoded - Human-readable version of the revert reason\n * @property {string} receipt.contractAddress - The address of the contract deployed in the transaction\n * @property {string[]} receipt.logs - Array of log entries generated by the transaction\n * @property {string[]} receipt.events - Array of events emitted during the transaction\n * @property {string} transactionHash - The hash of the transaction (duplicate of receipt.transactionHash)\n * @property {string} from - The sender address (duplicate of receipt.from)\n * @property {string} createdAt - Timestamp when the transaction was created\n * @property {string} address - The contract address involved in the transaction\n * @property {string} functionName - The name of the function called in the transaction\n * @property {boolean} isContract - Whether the transaction is a contract deployment\n */\nexport interface Transaction {\n receipt: {\n transactionHash: string;\n to: string;\n status: string;\n from: string;\n type: string;\n revertReason: string;\n revertReasonDecoded: string;\n logs: string[];\n events: string[];\n contractAddress: string;\n };\n transactionHash: string;\n from: string;\n createdAt: string;\n address: string;\n functionName: string;\n isContract: boolean;\n}\n\ninterface GetTransactionResponse {\n getTransaction: Transaction;\n}\n\n/**\n * Options for waiting for a transaction receipt\n *\n * @typedef {Object} WaitForTransactionReceiptOptions\n * @property {string} portalGraphqlEndpoint - The GraphQL endpoint URL for the Portal API\n * @property {string} accessToken - The access token for authentication with the Portal API\n * @property {number} [timeout] - Optional timeout in milliseconds before the operation fails\n */\nexport interface WaitForTransactionReceiptOptions {\n portalGraphqlEndpoint: string;\n accessToken: string;\n timeout?: number;\n}\n\n/**\n * Waits for a blockchain transaction receipt by subscribing to transaction updates via GraphQL.\n * This function polls until the transaction is confirmed or the timeout is reached.\n *\n * @param transactionHash - The hash of the transaction to wait for\n * @param options - Configuration options for the waiting process\n * @returns The transaction details including receipt information when the transaction is confirmed\n * @throws Error if the transaction receipt cannot be retrieved within the specified timeout\n *\n * @example\n * import { waitForTransactionReceipt } from \"@settlemint/sdk-portal\";\n *\n * const transaction = await waitForTransactionReceipt(\"0x123...\", {\n * portalGraphqlEndpoint: \"https://example.settlemint.com/graphql\",\n * accessToken: \"your-access-token\",\n * timeout: 30000 // 30 seconds timeout\n * });\n */\nexport async function waitForTransactionReceipt(transactionHash: string, options: WaitForTransactionReceiptOptions) {\n const wsClient = createClient({\n url: options.portalGraphqlEndpoint.toLowerCase().replace(\"/graphql\", `/${options.accessToken}/graphql`),\n });\n const subscription = wsClient.iterate<GetTransactionResponse>({\n query: `subscription getTransaction($transactionHash: String!) {\n getTransaction(transactionHash: $transactionHash) {\n receipt {\n transactionHash\n to\n status\n from\n type\n revertReason\n revertReasonDecoded\n logs\n events\n contractAddress\n }\n transactionHash\n from\n createdAt\n address\n functionName\n isContract\n }\n }`,\n variables: { transactionHash },\n });\n const promises = [getTransactionFromSubscription(subscription)];\n if (options.timeout) {\n promises.push(createTimeoutPromise(options.timeout));\n }\n\n return Promise.race(promises);\n}\n\nfunction createTimeoutPromise(timeout: number): Promise<never> {\n return new Promise((_, reject) => {\n setTimeout(() => reject(new Error(\"Transaction receipt not found\")), timeout);\n });\n}\n\nasync function getTransactionFromSubscription(\n subscription: AsyncIterableIterator<FormattedExecutionResult<GetTransactionResponse, unknown>>,\n): Promise<Transaction> {\n for await (const result of subscription) {\n if (result?.data?.getTransaction?.receipt) {\n return result.data.getTransaction;\n }\n }\n throw new Error(\"No transaction found\");\n}\n"],"mappings":"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","names":["import_gql"]}
package/dist/portal.d.cts CHANGED
@@ -2,6 +2,131 @@ import { AbstractSetupSchema, initGraphQLTada } from 'gql.tada';
2
2
  export { FragmentOf, ResultOf, VariablesOf, readFragment } from 'gql.tada';
3
3
  import { GraphQLClient } from 'graphql-request';
4
4
  import { z } from 'zod';
5
+ import { Address } from 'viem';
6
+
7
+ /**
8
+ * Options for handling a wallet verification challenge
9
+ *
10
+ * @typedef {Object} HandleWalletVerificationChallengeOptions
11
+ * @template {AbstractSetupSchema} Setup - The GraphQL schema setup type
12
+ * @property {GraphQLClient} portalClient - The portal client instance
13
+ * @property {initGraphQLTada<Setup>} portalGraphql - The GraphQL query builder
14
+ * @property {string} verificationId - The ID of the verification challenge
15
+ * @property {Address} userWalletAddress - The wallet address to verify
16
+ * @property {string | number} code - The verification code provided by the user
17
+ * @property {"otp" | "secret-code" | "pincode"} verificationType - The type of verification being performed
18
+ */
19
+ interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSchema> {
20
+ portalClient: GraphQLClient;
21
+ portalGraphql: initGraphQLTada<Setup>;
22
+ verificationId: string;
23
+ userWalletAddress: Address;
24
+ code: string | number;
25
+ verificationType: "otp" | "secret-code" | "pincode";
26
+ }
27
+ /**
28
+ * Handles a wallet verification challenge by generating an appropriate response
29
+ *
30
+ * @param options - The options for handling the wallet verification challenge
31
+ * @returns Promise resolving to an object containing the challenge response and optionally the verification ID
32
+ * @throws {ChallengeError} If the challenge cannot be created or is invalid
33
+ * @example
34
+ * import { createPortalClient } from "@settlemint/sdk-portal";
35
+ * import { handleWalletVerificationChallenge } from "@settlemint/sdk-portal";
36
+ *
37
+ * const { client, graphql } = createPortalClient({
38
+ * instance: "https://portal.example.com/graphql",
39
+ * accessToken: "your-access-token"
40
+ * });
41
+ *
42
+ * const result = await handleWalletVerificationChallenge({
43
+ * portalClient: client,
44
+ * portalGraphql: graphql,
45
+ * verificationId: "verification-123",
46
+ * userWalletAddress: "0x123...",
47
+ * code: "123456",
48
+ * verificationType: "otp"
49
+ * });
50
+ */
51
+ declare function handleWalletVerificationChallenge<const Setup extends AbstractSetupSchema>({ portalClient, portalGraphql, verificationId, userWalletAddress, code, verificationType, }: HandleWalletVerificationChallengeOptions<Setup>): Promise<{
52
+ challengeResponse: string;
53
+ verificationId?: string;
54
+ }>;
55
+
56
+ /**
57
+ * Represents the structure of a blockchain transaction with its receipt
58
+ *
59
+ * @typedef {Object} Transaction
60
+ * @property {Object} receipt - The transaction receipt details
61
+ * @property {string} receipt.transactionHash - The hash of the transaction
62
+ * @property {string} receipt.to - The recipient address of the transaction
63
+ * @property {string} receipt.status - The status of the transaction (success/failure)
64
+ * @property {string} receipt.from - The sender address of the transaction
65
+ * @property {string} receipt.type - The type of the transaction
66
+ * @property {string} receipt.revertReason - The reason for transaction reversion, if applicable
67
+ * @property {string} receipt.revertReasonDecoded - Human-readable version of the revert reason
68
+ * @property {string} receipt.contractAddress - The address of the contract deployed in the transaction
69
+ * @property {string[]} receipt.logs - Array of log entries generated by the transaction
70
+ * @property {string[]} receipt.events - Array of events emitted during the transaction
71
+ * @property {string} transactionHash - The hash of the transaction (duplicate of receipt.transactionHash)
72
+ * @property {string} from - The sender address (duplicate of receipt.from)
73
+ * @property {string} createdAt - Timestamp when the transaction was created
74
+ * @property {string} address - The contract address involved in the transaction
75
+ * @property {string} functionName - The name of the function called in the transaction
76
+ * @property {boolean} isContract - Whether the transaction is a contract deployment
77
+ */
78
+ interface Transaction {
79
+ receipt: {
80
+ transactionHash: string;
81
+ to: string;
82
+ status: string;
83
+ from: string;
84
+ type: string;
85
+ revertReason: string;
86
+ revertReasonDecoded: string;
87
+ logs: string[];
88
+ events: string[];
89
+ contractAddress: string;
90
+ };
91
+ transactionHash: string;
92
+ from: string;
93
+ createdAt: string;
94
+ address: string;
95
+ functionName: string;
96
+ isContract: boolean;
97
+ }
98
+ /**
99
+ * Options for waiting for a transaction receipt
100
+ *
101
+ * @typedef {Object} WaitForTransactionReceiptOptions
102
+ * @property {string} portalGraphqlEndpoint - The GraphQL endpoint URL for the Portal API
103
+ * @property {string} accessToken - The access token for authentication with the Portal API
104
+ * @property {number} [timeout] - Optional timeout in milliseconds before the operation fails
105
+ */
106
+ interface WaitForTransactionReceiptOptions {
107
+ portalGraphqlEndpoint: string;
108
+ accessToken: string;
109
+ timeout?: number;
110
+ }
111
+ /**
112
+ * Waits for a blockchain transaction receipt by subscribing to transaction updates via GraphQL.
113
+ * This function polls until the transaction is confirmed or the timeout is reached.
114
+ *
115
+ * @param transactionHash - The hash of the transaction to wait for
116
+ * @param options - Configuration options for the waiting process
117
+ * @returns The transaction details including receipt information when the transaction is confirmed
118
+ * @throws Error if the transaction receipt cannot be retrieved within the specified timeout
119
+ *
120
+ * @example
121
+ * import { waitForTransactionReceipt } from "@settlemint/sdk-portal";
122
+ *
123
+ * const transaction = await waitForTransactionReceipt("0x123...", {
124
+ * portalGraphqlEndpoint: "https://example.settlemint.com/graphql",
125
+ * accessToken: "your-access-token",
126
+ * timeout: 30000 // 30 seconds timeout
127
+ * });
128
+ */
129
+ declare function waitForTransactionReceipt(transactionHash: string, options: WaitForTransactionReceiptOptions): Promise<Transaction>;
5
130
 
6
131
  /**
7
132
  * Configuration options for the GraphQL client, excluding 'url' and 'exchanges'.
@@ -36,28 +161,33 @@ type ClientOptions = z.infer<typeof ClientOptionsSchema>;
36
161
  * @throws If the provided options fail validation
37
162
  *
38
163
  * @example
39
- * import { createPortalClient } from '@settlemint/sdk-portal';
164
+ * import { createPortalClient } from "@settlemint/sdk-portal";
165
+ * import { loadEnv } from "@settlemint/sdk-utils/environment";
166
+ * import { createLogger, requestLogger } from "@settlemint/sdk-utils/logging";
40
167
  * import type { introspection } from "@schemas/portal-env";
41
- * import { createLogger, requestLogger } from '@settlemint/sdk-utils/logging';
42
168
  *
169
+ * const env = await loadEnv(false, false);
43
170
  * const logger = createLogger();
44
171
  *
45
- * export const { client: portalClient, graphql: portalGraphql } = createPortalClient<{
172
+ * const { client: portalClient, graphql: portalGraphql } = createPortalClient<{
46
173
  * introspection: introspection;
47
174
  * disableMasking: true;
48
175
  * scalars: {
49
176
  * // Change unknown to the type you are using to store metadata
50
177
  * JSON: unknown;
51
178
  * };
52
- * }>({
53
- * instance: process.env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT,
54
- * accessToken: process.env.SETTLEMINT_ACCESS_TOKEN,
55
- * }, {
56
- * fetch: requestLogger(logger, "portal", fetch) as typeof fetch,
57
- * });
179
+ * }>(
180
+ * {
181
+ * instance: env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT!,
182
+ * accessToken: env.SETTLEMINT_ACCESS_TOKEN!,
183
+ * },
184
+ * {
185
+ * fetch: requestLogger(logger, "portal", fetch) as typeof fetch,
186
+ * },
187
+ * );
58
188
  *
59
189
  * // Making GraphQL queries
60
- * const query = graphql(`
190
+ * const query = portalGraphql(`
61
191
  * query GetPendingTransactions {
62
192
  * getPendingTransactions {
63
193
  * count
@@ -65,11 +195,11 @@ type ClientOptions = z.infer<typeof ClientOptionsSchema>;
65
195
  * }
66
196
  * `);
67
197
  *
68
- * const result = await client.request(query);
198
+ * const result = await portalClient.request(query);
69
199
  */
70
200
  declare function createPortalClient<const Setup extends AbstractSetupSchema>(options: ClientOptions, clientOptions?: RequestConfig): {
71
201
  client: GraphQLClient;
72
202
  graphql: initGraphQLTada<Setup>;
73
203
  };
74
204
 
75
- export { type ClientOptions, ClientOptionsSchema, type RequestConfig, createPortalClient };
205
+ export { type ClientOptions, ClientOptionsSchema, type HandleWalletVerificationChallengeOptions, type RequestConfig, type Transaction, type WaitForTransactionReceiptOptions, createPortalClient, handleWalletVerificationChallenge, waitForTransactionReceipt };
package/dist/portal.d.ts CHANGED
@@ -2,6 +2,131 @@ import { AbstractSetupSchema, initGraphQLTada } from 'gql.tada';
2
2
  export { FragmentOf, ResultOf, VariablesOf, readFragment } from 'gql.tada';
3
3
  import { GraphQLClient } from 'graphql-request';
4
4
  import { z } from 'zod';
5
+ import { Address } from 'viem';
6
+
7
+ /**
8
+ * Options for handling a wallet verification challenge
9
+ *
10
+ * @typedef {Object} HandleWalletVerificationChallengeOptions
11
+ * @template {AbstractSetupSchema} Setup - The GraphQL schema setup type
12
+ * @property {GraphQLClient} portalClient - The portal client instance
13
+ * @property {initGraphQLTada<Setup>} portalGraphql - The GraphQL query builder
14
+ * @property {string} verificationId - The ID of the verification challenge
15
+ * @property {Address} userWalletAddress - The wallet address to verify
16
+ * @property {string | number} code - The verification code provided by the user
17
+ * @property {"otp" | "secret-code" | "pincode"} verificationType - The type of verification being performed
18
+ */
19
+ interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSchema> {
20
+ portalClient: GraphQLClient;
21
+ portalGraphql: initGraphQLTada<Setup>;
22
+ verificationId: string;
23
+ userWalletAddress: Address;
24
+ code: string | number;
25
+ verificationType: "otp" | "secret-code" | "pincode";
26
+ }
27
+ /**
28
+ * Handles a wallet verification challenge by generating an appropriate response
29
+ *
30
+ * @param options - The options for handling the wallet verification challenge
31
+ * @returns Promise resolving to an object containing the challenge response and optionally the verification ID
32
+ * @throws {ChallengeError} If the challenge cannot be created or is invalid
33
+ * @example
34
+ * import { createPortalClient } from "@settlemint/sdk-portal";
35
+ * import { handleWalletVerificationChallenge } from "@settlemint/sdk-portal";
36
+ *
37
+ * const { client, graphql } = createPortalClient({
38
+ * instance: "https://portal.example.com/graphql",
39
+ * accessToken: "your-access-token"
40
+ * });
41
+ *
42
+ * const result = await handleWalletVerificationChallenge({
43
+ * portalClient: client,
44
+ * portalGraphql: graphql,
45
+ * verificationId: "verification-123",
46
+ * userWalletAddress: "0x123...",
47
+ * code: "123456",
48
+ * verificationType: "otp"
49
+ * });
50
+ */
51
+ declare function handleWalletVerificationChallenge<const Setup extends AbstractSetupSchema>({ portalClient, portalGraphql, verificationId, userWalletAddress, code, verificationType, }: HandleWalletVerificationChallengeOptions<Setup>): Promise<{
52
+ challengeResponse: string;
53
+ verificationId?: string;
54
+ }>;
55
+
56
+ /**
57
+ * Represents the structure of a blockchain transaction with its receipt
58
+ *
59
+ * @typedef {Object} Transaction
60
+ * @property {Object} receipt - The transaction receipt details
61
+ * @property {string} receipt.transactionHash - The hash of the transaction
62
+ * @property {string} receipt.to - The recipient address of the transaction
63
+ * @property {string} receipt.status - The status of the transaction (success/failure)
64
+ * @property {string} receipt.from - The sender address of the transaction
65
+ * @property {string} receipt.type - The type of the transaction
66
+ * @property {string} receipt.revertReason - The reason for transaction reversion, if applicable
67
+ * @property {string} receipt.revertReasonDecoded - Human-readable version of the revert reason
68
+ * @property {string} receipt.contractAddress - The address of the contract deployed in the transaction
69
+ * @property {string[]} receipt.logs - Array of log entries generated by the transaction
70
+ * @property {string[]} receipt.events - Array of events emitted during the transaction
71
+ * @property {string} transactionHash - The hash of the transaction (duplicate of receipt.transactionHash)
72
+ * @property {string} from - The sender address (duplicate of receipt.from)
73
+ * @property {string} createdAt - Timestamp when the transaction was created
74
+ * @property {string} address - The contract address involved in the transaction
75
+ * @property {string} functionName - The name of the function called in the transaction
76
+ * @property {boolean} isContract - Whether the transaction is a contract deployment
77
+ */
78
+ interface Transaction {
79
+ receipt: {
80
+ transactionHash: string;
81
+ to: string;
82
+ status: string;
83
+ from: string;
84
+ type: string;
85
+ revertReason: string;
86
+ revertReasonDecoded: string;
87
+ logs: string[];
88
+ events: string[];
89
+ contractAddress: string;
90
+ };
91
+ transactionHash: string;
92
+ from: string;
93
+ createdAt: string;
94
+ address: string;
95
+ functionName: string;
96
+ isContract: boolean;
97
+ }
98
+ /**
99
+ * Options for waiting for a transaction receipt
100
+ *
101
+ * @typedef {Object} WaitForTransactionReceiptOptions
102
+ * @property {string} portalGraphqlEndpoint - The GraphQL endpoint URL for the Portal API
103
+ * @property {string} accessToken - The access token for authentication with the Portal API
104
+ * @property {number} [timeout] - Optional timeout in milliseconds before the operation fails
105
+ */
106
+ interface WaitForTransactionReceiptOptions {
107
+ portalGraphqlEndpoint: string;
108
+ accessToken: string;
109
+ timeout?: number;
110
+ }
111
+ /**
112
+ * Waits for a blockchain transaction receipt by subscribing to transaction updates via GraphQL.
113
+ * This function polls until the transaction is confirmed or the timeout is reached.
114
+ *
115
+ * @param transactionHash - The hash of the transaction to wait for
116
+ * @param options - Configuration options for the waiting process
117
+ * @returns The transaction details including receipt information when the transaction is confirmed
118
+ * @throws Error if the transaction receipt cannot be retrieved within the specified timeout
119
+ *
120
+ * @example
121
+ * import { waitForTransactionReceipt } from "@settlemint/sdk-portal";
122
+ *
123
+ * const transaction = await waitForTransactionReceipt("0x123...", {
124
+ * portalGraphqlEndpoint: "https://example.settlemint.com/graphql",
125
+ * accessToken: "your-access-token",
126
+ * timeout: 30000 // 30 seconds timeout
127
+ * });
128
+ */
129
+ declare function waitForTransactionReceipt(transactionHash: string, options: WaitForTransactionReceiptOptions): Promise<Transaction>;
5
130
 
6
131
  /**
7
132
  * Configuration options for the GraphQL client, excluding 'url' and 'exchanges'.
@@ -36,28 +161,33 @@ type ClientOptions = z.infer<typeof ClientOptionsSchema>;
36
161
  * @throws If the provided options fail validation
37
162
  *
38
163
  * @example
39
- * import { createPortalClient } from '@settlemint/sdk-portal';
164
+ * import { createPortalClient } from "@settlemint/sdk-portal";
165
+ * import { loadEnv } from "@settlemint/sdk-utils/environment";
166
+ * import { createLogger, requestLogger } from "@settlemint/sdk-utils/logging";
40
167
  * import type { introspection } from "@schemas/portal-env";
41
- * import { createLogger, requestLogger } from '@settlemint/sdk-utils/logging';
42
168
  *
169
+ * const env = await loadEnv(false, false);
43
170
  * const logger = createLogger();
44
171
  *
45
- * export const { client: portalClient, graphql: portalGraphql } = createPortalClient<{
172
+ * const { client: portalClient, graphql: portalGraphql } = createPortalClient<{
46
173
  * introspection: introspection;
47
174
  * disableMasking: true;
48
175
  * scalars: {
49
176
  * // Change unknown to the type you are using to store metadata
50
177
  * JSON: unknown;
51
178
  * };
52
- * }>({
53
- * instance: process.env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT,
54
- * accessToken: process.env.SETTLEMINT_ACCESS_TOKEN,
55
- * }, {
56
- * fetch: requestLogger(logger, "portal", fetch) as typeof fetch,
57
- * });
179
+ * }>(
180
+ * {
181
+ * instance: env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT!,
182
+ * accessToken: env.SETTLEMINT_ACCESS_TOKEN!,
183
+ * },
184
+ * {
185
+ * fetch: requestLogger(logger, "portal", fetch) as typeof fetch,
186
+ * },
187
+ * );
58
188
  *
59
189
  * // Making GraphQL queries
60
- * const query = graphql(`
190
+ * const query = portalGraphql(`
61
191
  * query GetPendingTransactions {
62
192
  * getPendingTransactions {
63
193
  * count
@@ -65,11 +195,11 @@ type ClientOptions = z.infer<typeof ClientOptionsSchema>;
65
195
  * }
66
196
  * `);
67
197
  *
68
- * const result = await client.request(query);
198
+ * const result = await portalClient.request(query);
69
199
  */
70
200
  declare function createPortalClient<const Setup extends AbstractSetupSchema>(options: ClientOptions, clientOptions?: RequestConfig): {
71
201
  client: GraphQLClient;
72
202
  graphql: initGraphQLTada<Setup>;
73
203
  };
74
204
 
75
- export { type ClientOptions, ClientOptionsSchema, type RequestConfig, createPortalClient };
205
+ export { type ClientOptions, ClientOptionsSchema, type HandleWalletVerificationChallengeOptions, type RequestConfig, type Transaction, type WaitForTransactionReceiptOptions, createPortalClient, handleWalletVerificationChallenge, waitForTransactionReceipt };
package/dist/portal.mjs CHANGED
@@ -4,6 +4,137 @@ import { ApplicationAccessTokenSchema, UrlOrPathSchema, validate } from "@settle
4
4
  import { initGraphQLTada } from "gql.tada";
5
5
  import { GraphQLClient } from "graphql-request";
6
6
  import { z } from "zod";
7
+
8
+ // src/utils/wallet-verification-challenge.ts
9
+ import { createHash } from "node:crypto";
10
+ var ChallengeError = class extends Error {
11
+ code;
12
+ constructor(message, code) {
13
+ super(message);
14
+ this.name = "ChallengeError";
15
+ this.code = code;
16
+ }
17
+ };
18
+ function hashPincode(pincode, salt) {
19
+ return createHash("sha256").update(`${salt}${pincode}`).digest("hex");
20
+ }
21
+ function generateResponse(pincode, salt, challenge) {
22
+ const hashedPincode = hashPincode(pincode, salt);
23
+ return createHash("sha256").update(`${hashedPincode}_${challenge}`).digest("hex");
24
+ }
25
+ async function handleWalletVerificationChallenge({
26
+ portalClient,
27
+ portalGraphql,
28
+ verificationId,
29
+ userWalletAddress,
30
+ code,
31
+ verificationType
32
+ }) {
33
+ try {
34
+ if (verificationType === "otp") {
35
+ return {
36
+ challengeResponse: code.toString(),
37
+ verificationId
38
+ };
39
+ }
40
+ if (verificationType === "secret-code") {
41
+ const formattedCode = code.toString().replace(/(.{5})(?=.)/, "$1-");
42
+ return {
43
+ challengeResponse: formattedCode,
44
+ verificationId
45
+ };
46
+ }
47
+ const verificationChallenges = await portalClient.request(
48
+ portalGraphql(`
49
+ mutation CreateWalletVerificationChallenges($userWalletAddress: String!, $verificationId: String!) {
50
+ createWalletVerificationChallenges(userWalletAddress: $userWalletAddress, verificationId: $verificationId) {
51
+ challenge
52
+ id
53
+ name
54
+ verificationType
55
+ }
56
+ }
57
+ `),
58
+ {
59
+ userWalletAddress,
60
+ verificationId
61
+ }
62
+ );
63
+ if (!verificationChallenges.createWalletVerificationChallenges?.length) {
64
+ throw new ChallengeError("No verification challenges received", "NO_CHALLENGES");
65
+ }
66
+ const walletVerificationChallenge = verificationChallenges.createWalletVerificationChallenges.find(
67
+ (challenge) => challenge.id === verificationId
68
+ );
69
+ if (!walletVerificationChallenge?.challenge?.secret || !walletVerificationChallenge?.challenge?.salt) {
70
+ throw new ChallengeError("Invalid challenge format", "INVALID_CHALLENGE");
71
+ }
72
+ const { secret, salt } = walletVerificationChallenge.challenge;
73
+ const challengeResponse = generateResponse(code.toString(), salt, secret);
74
+ return {
75
+ challengeResponse,
76
+ verificationId
77
+ };
78
+ } catch (error) {
79
+ if (error instanceof ChallengeError) {
80
+ throw error;
81
+ }
82
+ throw new ChallengeError("Failed to process wallet verification challenge", "CHALLENGE_PROCESSING_ERROR");
83
+ }
84
+ }
85
+
86
+ // src/utils/wait-for-transaction-receipt.ts
87
+ import { createClient } from "graphql-ws";
88
+ async function waitForTransactionReceipt(transactionHash, options) {
89
+ const wsClient = createClient({
90
+ url: options.portalGraphqlEndpoint.toLowerCase().replace("/graphql", `/${options.accessToken}/graphql`)
91
+ });
92
+ const subscription = wsClient.iterate({
93
+ query: `subscription getTransaction($transactionHash: String!) {
94
+ getTransaction(transactionHash: $transactionHash) {
95
+ receipt {
96
+ transactionHash
97
+ to
98
+ status
99
+ from
100
+ type
101
+ revertReason
102
+ revertReasonDecoded
103
+ logs
104
+ events
105
+ contractAddress
106
+ }
107
+ transactionHash
108
+ from
109
+ createdAt
110
+ address
111
+ functionName
112
+ isContract
113
+ }
114
+ }`,
115
+ variables: { transactionHash }
116
+ });
117
+ const promises = [getTransactionFromSubscription(subscription)];
118
+ if (options.timeout) {
119
+ promises.push(createTimeoutPromise(options.timeout));
120
+ }
121
+ return Promise.race(promises);
122
+ }
123
+ function createTimeoutPromise(timeout) {
124
+ return new Promise((_, reject) => {
125
+ setTimeout(() => reject(new Error("Transaction receipt not found")), timeout);
126
+ });
127
+ }
128
+ async function getTransactionFromSubscription(subscription) {
129
+ for await (const result of subscription) {
130
+ if (result?.data?.getTransaction?.receipt) {
131
+ return result.data.getTransaction;
132
+ }
133
+ }
134
+ throw new Error("No transaction found");
135
+ }
136
+
137
+ // src/portal.ts
7
138
  import { readFragment } from "gql.tada";
8
139
  var ClientOptionsSchema = z.object({
9
140
  instance: UrlOrPathSchema,
@@ -26,6 +157,8 @@ function createPortalClient(options, clientOptions) {
26
157
  export {
27
158
  ClientOptionsSchema,
28
159
  createPortalClient,
29
- readFragment
160
+ handleWalletVerificationChallenge,
161
+ readFragment,
162
+ waitForTransactionReceipt
30
163
  };
31
164
  //# sourceMappingURL=portal.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/portal.ts"],"sourcesContent":["import { ensureServer } from \"@settlemint/sdk-utils/runtime\";\nimport { ApplicationAccessTokenSchema, UrlOrPathSchema, validate } from \"@settlemint/sdk-utils/validation\";\nimport { type AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport { GraphQLClient } from \"graphql-request\";\nimport { z } from \"zod\";\n\n/**\n * Configuration options for the GraphQL client, excluding 'url' and 'exchanges'.\n */\nexport type RequestConfig = ConstructorParameters<typeof GraphQLClient>[1];\n\n/**\n * Schema for validating Portal client configuration options.\n */\nexport const ClientOptionsSchema = z.object({\n instance: UrlOrPathSchema,\n accessToken: ApplicationAccessTokenSchema,\n cache: z.enum([\"default\", \"force-cache\", \"no-cache\", \"no-store\", \"only-if-cached\", \"reload\"]).optional(),\n});\n\n/**\n * Type representing the validated client options.\n */\nexport type ClientOptions = z.infer<typeof ClientOptionsSchema>;\n\n/**\n * Creates a Portal GraphQL client with the provided configuration.\n *\n * @param options - Configuration options for the Portal client\n * @param clientOptions - Additional GraphQL client configuration options\n * @returns An object containing the configured GraphQL client and graphql helper function\n * @throws If the provided options fail validation\n *\n * @example\n * import { createPortalClient } from '@settlemint/sdk-portal';\n * import type { introspection } from \"@schemas/portal-env\";\n * import { createLogger, requestLogger } from '@settlemint/sdk-utils/logging';\n *\n * const logger = createLogger();\n *\n * export const { client: portalClient, graphql: portalGraphql } = createPortalClient<{\n * introspection: introspection;\n * disableMasking: true;\n * scalars: {\n * // Change unknown to the type you are using to store metadata\n * JSON: unknown;\n * };\n * }>({\n * instance: process.env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT,\n * accessToken: process.env.SETTLEMINT_ACCESS_TOKEN,\n * }, {\n * fetch: requestLogger(logger, \"portal\", fetch) as typeof fetch,\n * });\n *\n * // Making GraphQL queries\n * const query = graphql(`\n * query GetPendingTransactions {\n * getPendingTransactions {\n * count\n * }\n * }\n * `);\n *\n * const result = await client.request(query);\n */\nexport function createPortalClient<const Setup extends AbstractSetupSchema>(\n options: ClientOptions,\n clientOptions?: RequestConfig,\n): {\n client: GraphQLClient;\n graphql: initGraphQLTada<Setup>;\n} {\n ensureServer();\n const validatedOptions = validate(ClientOptionsSchema, options);\n const graphql = initGraphQLTada<Setup>();\n const fullUrl = new URL(validatedOptions.instance).toString();\n\n return {\n client: new GraphQLClient(fullUrl, {\n ...clientOptions,\n headers: { ...(clientOptions?.headers ?? {}), \"x-auth-token\": validatedOptions.accessToken },\n }),\n graphql,\n };\n}\n\nexport { readFragment } from \"gql.tada\";\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\n"],"mappings":";AAAA,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B,iBAAiB,gBAAgB;AACxE,SAAmC,uBAAuB;AAC1D,SAAS,qBAAqB;AAC9B,SAAS,SAAS;AAkFlB,SAAS,oBAAoB;AAxEtB,IAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,UAAU;AAAA,EACV,aAAa;AAAA,EACb,OAAO,EAAE,KAAK,CAAC,WAAW,eAAe,YAAY,YAAY,kBAAkB,QAAQ,CAAC,EAAE,SAAS;AACzG,CAAC;AA+CM,SAAS,mBACd,SACA,eAIA;AACA,eAAa;AACb,QAAM,mBAAmB,SAAS,qBAAqB,OAAO;AAC9D,QAAM,UAAU,gBAAuB;AACvC,QAAM,UAAU,IAAI,IAAI,iBAAiB,QAAQ,EAAE,SAAS;AAE5D,SAAO;AAAA,IACL,QAAQ,IAAI,cAAc,SAAS;AAAA,MACjC,GAAG;AAAA,MACH,SAAS,EAAE,GAAI,eAAe,WAAW,CAAC,GAAI,gBAAgB,iBAAiB,YAAY;AAAA,IAC7F,CAAC;AAAA,IACD;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/portal.ts","../src/utils/wallet-verification-challenge.ts","../src/utils/wait-for-transaction-receipt.ts"],"sourcesContent":["import { ensureServer } from \"@settlemint/sdk-utils/runtime\";\nimport { ApplicationAccessTokenSchema, UrlOrPathSchema, validate } from \"@settlemint/sdk-utils/validation\";\nimport { type AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport { GraphQLClient } from \"graphql-request\";\nimport { z } from \"zod\";\n\n/**\n * Configuration options for the GraphQL client, excluding 'url' and 'exchanges'.\n */\nexport type RequestConfig = ConstructorParameters<typeof GraphQLClient>[1];\n\n/**\n * Schema for validating Portal client configuration options.\n */\nexport const ClientOptionsSchema = z.object({\n instance: UrlOrPathSchema,\n accessToken: ApplicationAccessTokenSchema,\n cache: z.enum([\"default\", \"force-cache\", \"no-cache\", \"no-store\", \"only-if-cached\", \"reload\"]).optional(),\n});\n\n/**\n * Type representing the validated client options.\n */\nexport type ClientOptions = z.infer<typeof ClientOptionsSchema>;\n\n/**\n * Creates a Portal GraphQL client with the provided configuration.\n *\n * @param options - Configuration options for the Portal client\n * @param clientOptions - Additional GraphQL client configuration options\n * @returns An object containing the configured GraphQL client and graphql helper function\n * @throws If the provided options fail validation\n *\n * @example\n * import { createPortalClient } from \"@settlemint/sdk-portal\";\n * import { loadEnv } from \"@settlemint/sdk-utils/environment\";\n * import { createLogger, requestLogger } from \"@settlemint/sdk-utils/logging\";\n * import type { introspection } from \"@schemas/portal-env\";\n *\n * const env = await loadEnv(false, false);\n * const logger = createLogger();\n *\n * const { client: portalClient, graphql: portalGraphql } = createPortalClient<{\n * introspection: introspection;\n * disableMasking: true;\n * scalars: {\n * // Change unknown to the type you are using to store metadata\n * JSON: unknown;\n * };\n * }>(\n * {\n * instance: env.SETTLEMINT_PORTAL_GRAPHQL_ENDPOINT!,\n * accessToken: env.SETTLEMINT_ACCESS_TOKEN!,\n * },\n * {\n * fetch: requestLogger(logger, \"portal\", fetch) as typeof fetch,\n * },\n * );\n *\n * // Making GraphQL queries\n * const query = portalGraphql(`\n * query GetPendingTransactions {\n * getPendingTransactions {\n * count\n * }\n * }\n * `);\n *\n * const result = await portalClient.request(query);\n */\nexport function createPortalClient<const Setup extends AbstractSetupSchema>(\n options: ClientOptions,\n clientOptions?: RequestConfig,\n): {\n client: GraphQLClient;\n graphql: initGraphQLTada<Setup>;\n} {\n ensureServer();\n const validatedOptions = validate(ClientOptionsSchema, options);\n const graphql = initGraphQLTada<Setup>();\n const fullUrl = new URL(validatedOptions.instance).toString();\n\n return {\n client: new GraphQLClient(fullUrl, {\n ...clientOptions,\n headers: { ...(clientOptions?.headers ?? {}), \"x-auth-token\": validatedOptions.accessToken },\n }),\n graphql,\n };\n}\n\nexport {\n handleWalletVerificationChallenge,\n type HandleWalletVerificationChallengeOptions,\n} from \"./utils/wallet-verification-challenge.js\";\nexport {\n waitForTransactionReceipt,\n type Transaction,\n type WaitForTransactionReceiptOptions,\n} from \"./utils/wait-for-transaction-receipt.js\";\nexport { readFragment } from \"gql.tada\";\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\n","import { createHash } from \"node:crypto\";\nimport type { AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport type { GraphQLClient } from \"graphql-request\";\nimport type { Address } from \"viem\";\n\n/**\n * Custom error class for challenge-related errors\n */\nexport class ChallengeError extends Error {\n readonly code: string;\n\n constructor(message: string, code: string) {\n super(message);\n this.name = \"ChallengeError\";\n this.code = code;\n }\n}\n\n/**\n * Represents the structure of a wallet verification challenge\n */\ninterface WalletVerificationChallenge {\n challenge: {\n secret: string;\n salt: string;\n };\n id: string;\n name: string;\n verificationType: string;\n}\n\n/**\n * Response type for the CreateWalletVerificationChallenges mutation\n */\ninterface CreateWalletVerificationChallengesResponse {\n createWalletVerificationChallenges: WalletVerificationChallenge[];\n}\n\n/**\n * Hashes a pincode with a salt using SHA-256\n * @param pincode - The pincode to hash\n * @param salt - The salt to use in hashing\n * @returns The hashed pincode as a hex string\n */\nfunction hashPincode(pincode: string, salt: string): string {\n return createHash(\"sha256\").update(`${salt}${pincode}`).digest(\"hex\");\n}\n\n/**\n * Generates a challenge response by combining a hashed pincode with a challenge\n * @param pincode - The user's pincode\n * @param salt - The salt provided in the challenge\n * @param challenge - The challenge secret\n * @returns The challenge response as a hex string\n */\nfunction generateResponse(pincode: string, salt: string, challenge: string): string {\n const hashedPincode = hashPincode(pincode, salt);\n return createHash(\"sha256\").update(`${hashedPincode}_${challenge}`).digest(\"hex\");\n}\n\n/**\n * Options for handling a wallet verification challenge\n *\n * @typedef {Object} HandleWalletVerificationChallengeOptions\n * @template {AbstractSetupSchema} Setup - The GraphQL schema setup type\n * @property {GraphQLClient} portalClient - The portal client instance\n * @property {initGraphQLTada<Setup>} portalGraphql - The GraphQL query builder\n * @property {string} verificationId - The ID of the verification challenge\n * @property {Address} userWalletAddress - The wallet address to verify\n * @property {string | number} code - The verification code provided by the user\n * @property {\"otp\" | \"secret-code\" | \"pincode\"} verificationType - The type of verification being performed\n */\nexport interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSchema> {\n portalClient: GraphQLClient;\n portalGraphql: initGraphQLTada<Setup>;\n verificationId: string;\n userWalletAddress: Address;\n code: string | number;\n verificationType: \"otp\" | \"secret-code\" | \"pincode\";\n}\n\n/**\n * Handles a wallet verification challenge by generating an appropriate response\n *\n * @param options - The options for handling the wallet verification challenge\n * @returns Promise resolving to an object containing the challenge response and optionally the verification ID\n * @throws {ChallengeError} If the challenge cannot be created or is invalid\n * @example\n * import { createPortalClient } from \"@settlemint/sdk-portal\";\n * import { handleWalletVerificationChallenge } from \"@settlemint/sdk-portal\";\n *\n * const { client, graphql } = createPortalClient({\n * instance: \"https://portal.example.com/graphql\",\n * accessToken: \"your-access-token\"\n * });\n *\n * const result = await handleWalletVerificationChallenge({\n * portalClient: client,\n * portalGraphql: graphql,\n * verificationId: \"verification-123\",\n * userWalletAddress: \"0x123...\",\n * code: \"123456\",\n * verificationType: \"otp\"\n * });\n */\nexport async function handleWalletVerificationChallenge<const Setup extends AbstractSetupSchema>({\n portalClient,\n portalGraphql,\n verificationId,\n userWalletAddress,\n code,\n verificationType,\n}: HandleWalletVerificationChallengeOptions<Setup>): Promise<{\n challengeResponse: string;\n verificationId?: string;\n}> {\n try {\n if (verificationType === \"otp\") {\n return {\n challengeResponse: code.toString(),\n verificationId,\n };\n }\n\n if (verificationType === \"secret-code\") {\n // Add - separator to the code\n const formattedCode = code.toString().replace(/(.{5})(?=.)/, \"$1-\");\n return {\n challengeResponse: formattedCode,\n verificationId,\n };\n }\n\n const verificationChallenges = await portalClient.request<CreateWalletVerificationChallengesResponse>(\n portalGraphql(`\n mutation CreateWalletVerificationChallenges($userWalletAddress: String!, $verificationId: String!) {\n createWalletVerificationChallenges(userWalletAddress: $userWalletAddress, verificationId: $verificationId) {\n challenge\n id\n name\n verificationType\n }\n }\n `),\n {\n userWalletAddress,\n verificationId,\n },\n );\n\n if (!verificationChallenges.createWalletVerificationChallenges?.length) {\n throw new ChallengeError(\"No verification challenges received\", \"NO_CHALLENGES\");\n }\n\n const walletVerificationChallenge = verificationChallenges.createWalletVerificationChallenges.find(\n (challenge) => challenge.id === verificationId,\n );\n\n if (!walletVerificationChallenge?.challenge?.secret || !walletVerificationChallenge?.challenge?.salt) {\n throw new ChallengeError(\"Invalid challenge format\", \"INVALID_CHALLENGE\");\n }\n\n const { secret, salt } = walletVerificationChallenge.challenge;\n const challengeResponse = generateResponse(code.toString(), salt, secret);\n return {\n challengeResponse,\n verificationId,\n };\n } catch (error) {\n if (error instanceof ChallengeError) {\n throw error;\n }\n throw new ChallengeError(\"Failed to process wallet verification challenge\", \"CHALLENGE_PROCESSING_ERROR\");\n }\n}\n","import { type FormattedExecutionResult, createClient } from \"graphql-ws\";\n\n/**\n * Represents the structure of a blockchain transaction with its receipt\n *\n * @typedef {Object} Transaction\n * @property {Object} receipt - The transaction receipt details\n * @property {string} receipt.transactionHash - The hash of the transaction\n * @property {string} receipt.to - The recipient address of the transaction\n * @property {string} receipt.status - The status of the transaction (success/failure)\n * @property {string} receipt.from - The sender address of the transaction\n * @property {string} receipt.type - The type of the transaction\n * @property {string} receipt.revertReason - The reason for transaction reversion, if applicable\n * @property {string} receipt.revertReasonDecoded - Human-readable version of the revert reason\n * @property {string} receipt.contractAddress - The address of the contract deployed in the transaction\n * @property {string[]} receipt.logs - Array of log entries generated by the transaction\n * @property {string[]} receipt.events - Array of events emitted during the transaction\n * @property {string} transactionHash - The hash of the transaction (duplicate of receipt.transactionHash)\n * @property {string} from - The sender address (duplicate of receipt.from)\n * @property {string} createdAt - Timestamp when the transaction was created\n * @property {string} address - The contract address involved in the transaction\n * @property {string} functionName - The name of the function called in the transaction\n * @property {boolean} isContract - Whether the transaction is a contract deployment\n */\nexport interface Transaction {\n receipt: {\n transactionHash: string;\n to: string;\n status: string;\n from: string;\n type: string;\n revertReason: string;\n revertReasonDecoded: string;\n logs: string[];\n events: string[];\n contractAddress: string;\n };\n transactionHash: string;\n from: string;\n createdAt: string;\n address: string;\n functionName: string;\n isContract: boolean;\n}\n\ninterface GetTransactionResponse {\n getTransaction: Transaction;\n}\n\n/**\n * Options for waiting for a transaction receipt\n *\n * @typedef {Object} WaitForTransactionReceiptOptions\n * @property {string} portalGraphqlEndpoint - The GraphQL endpoint URL for the Portal API\n * @property {string} accessToken - The access token for authentication with the Portal API\n * @property {number} [timeout] - Optional timeout in milliseconds before the operation fails\n */\nexport interface WaitForTransactionReceiptOptions {\n portalGraphqlEndpoint: string;\n accessToken: string;\n timeout?: number;\n}\n\n/**\n * Waits for a blockchain transaction receipt by subscribing to transaction updates via GraphQL.\n * This function polls until the transaction is confirmed or the timeout is reached.\n *\n * @param transactionHash - The hash of the transaction to wait for\n * @param options - Configuration options for the waiting process\n * @returns The transaction details including receipt information when the transaction is confirmed\n * @throws Error if the transaction receipt cannot be retrieved within the specified timeout\n *\n * @example\n * import { waitForTransactionReceipt } from \"@settlemint/sdk-portal\";\n *\n * const transaction = await waitForTransactionReceipt(\"0x123...\", {\n * portalGraphqlEndpoint: \"https://example.settlemint.com/graphql\",\n * accessToken: \"your-access-token\",\n * timeout: 30000 // 30 seconds timeout\n * });\n */\nexport async function waitForTransactionReceipt(transactionHash: string, options: WaitForTransactionReceiptOptions) {\n const wsClient = createClient({\n url: options.portalGraphqlEndpoint.toLowerCase().replace(\"/graphql\", `/${options.accessToken}/graphql`),\n });\n const subscription = wsClient.iterate<GetTransactionResponse>({\n query: `subscription getTransaction($transactionHash: String!) {\n getTransaction(transactionHash: $transactionHash) {\n receipt {\n transactionHash\n to\n status\n from\n type\n revertReason\n revertReasonDecoded\n logs\n events\n contractAddress\n }\n transactionHash\n from\n createdAt\n address\n functionName\n isContract\n }\n }`,\n variables: { transactionHash },\n });\n const promises = [getTransactionFromSubscription(subscription)];\n if (options.timeout) {\n promises.push(createTimeoutPromise(options.timeout));\n }\n\n return Promise.race(promises);\n}\n\nfunction createTimeoutPromise(timeout: number): Promise<never> {\n return new Promise((_, reject) => {\n setTimeout(() => reject(new Error(\"Transaction receipt not found\")), timeout);\n });\n}\n\nasync function getTransactionFromSubscription(\n subscription: AsyncIterableIterator<FormattedExecutionResult<GetTransactionResponse, unknown>>,\n): Promise<Transaction> {\n for await (const result of subscription) {\n if (result?.data?.getTransaction?.receipt) {\n return result.data.getTransaction;\n }\n }\n throw new Error(\"No transaction found\");\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@settlemint/sdk-portal",
3
3
  "description": "Portal API client module for SettleMint SDK, providing access to smart contract portal services and APIs",
4
- "version": "2.2.0-maind07ccd95",
4
+ "version": "2.2.0-pr0a1949d3",
5
5
  "type": "module",
6
6
  "private": false,
7
7
  "license": "FSL-1.1-MIT",
@@ -47,12 +47,16 @@
47
47
  "typecheck": "tsc --noEmit",
48
48
  "publish-npm": "bun publish --tag ${TAG} --access public || exit 0",
49
49
  "prepack": "cp ../../LICENSE .",
50
+ "codegen": "gql-tada generate-output",
50
51
  "docs": "typedoc --options '../../typedoc.config.mjs' --entryPoints src/portal.ts --out ./docs"
51
52
  },
52
- "devDependencies": {},
53
+ "devDependencies": {
54
+ "viem": "^2"
55
+ },
53
56
  "dependencies": {
54
57
  "gql.tada": "^1",
55
- "@settlemint/sdk-utils": "2.2.0-maind07ccd95",
58
+ "graphql-ws": "^6",
59
+ "@settlemint/sdk-utils": "2.2.0-pr0a1949d3",
56
60
  "graphql-request": "^7",
57
61
  "zod": "^3"
58
62
  },