@settlemint/sdk-portal 2.5.13 → 2.5.14-pr16f805ec

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
@@ -601,7 +601,7 @@ console.log("Transaction hash:", result.StableCoinFactoryCreate?.transactionHash
601
601
 
602
602
  > **createPortalClient**\<`Setup`\>(`options`, `clientOptions?`): `object`
603
603
 
604
- Defined in: [sdk/portal/src/portal.ts:72](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/portal.ts#L72)
604
+ Defined in: [sdk/portal/src/portal.ts:72](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/portal.ts#L72)
605
605
 
606
606
  Creates a Portal GraphQL client with the provided configuration.
607
607
 
@@ -629,8 +629,8 @@ An object containing the configured GraphQL client and graphql helper function
629
629
 
630
630
  | Name | Type | Defined in |
631
631
  | ------ | ------ | ------ |
632
- | `client` | `GraphQLClient` | [sdk/portal/src/portal.ts:76](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/portal.ts#L76) |
633
- | `graphql` | `initGraphQLTada`\<`Setup`\> | [sdk/portal/src/portal.ts:77](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/portal.ts#L77) |
632
+ | `client` | `GraphQLClient` | [sdk/portal/src/portal.ts:76](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/portal.ts#L76) |
633
+ | `graphql` | `initGraphQLTada`\<`Setup`\> | [sdk/portal/src/portal.ts:77](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/portal.ts#L77) |
634
634
 
635
635
  ##### Throws
636
636
 
@@ -682,7 +682,7 @@ const result = await portalClient.request(query);
682
682
 
683
683
  > **getWebsocketClient**(`options`): `Client`
684
684
 
685
- Defined in: [sdk/portal/src/utils/websocket-client.ts:30](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/websocket-client.ts#L30)
685
+ Defined in: [sdk/portal/src/utils/websocket-client.ts:30](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/websocket-client.ts#L30)
686
686
 
687
687
  Creates a GraphQL WebSocket client for the Portal API
688
688
 
@@ -715,7 +715,7 @@ const client = getWebsocketClient({
715
715
 
716
716
  > **handleWalletVerificationChallenge**\<`Setup`\>(`options`): `Promise`\<\{ `challengeResponse`: `string`; `verificationId?`: `string`; \}\>
717
717
 
718
- Defined in: [sdk/portal/src/utils/wallet-verification-challenge.ts:103](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wallet-verification-challenge.ts#L103)
718
+ Defined in: [sdk/portal/src/utils/wallet-verification-challenge.ts:103](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wallet-verification-challenge.ts#L103)
719
719
 
720
720
  Handles a wallet verification challenge by generating an appropriate response
721
721
 
@@ -768,7 +768,7 @@ const result = await handleWalletVerificationChallenge({
768
768
 
769
769
  > **waitForTransactionReceipt**(`transactionHash`, `options`): `Promise`\<[`Transaction`](#transaction)\>
770
770
 
771
- Defined in: [sdk/portal/src/utils/wait-for-transaction-receipt.ts:80](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L80)
771
+ Defined in: [sdk/portal/src/utils/wait-for-transaction-receipt.ts:80](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L80)
772
772
 
773
773
  Waits for a blockchain transaction receipt by subscribing to transaction updates via GraphQL.
774
774
  This function polls until the transaction is confirmed or the timeout is reached.
@@ -806,7 +806,7 @@ const transaction = await waitForTransactionReceipt("0x123...", {
806
806
 
807
807
  #### HandleWalletVerificationChallengeOptions\<Setup\>
808
808
 
809
- Defined in: [sdk/portal/src/utils/wallet-verification-challenge.ts:64](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wallet-verification-challenge.ts#L64)
809
+ Defined in: [sdk/portal/src/utils/wallet-verification-challenge.ts:64](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wallet-verification-challenge.ts#L64)
810
810
 
811
811
  Options for handling a wallet verification challenge
812
812
 
@@ -820,18 +820,18 @@ Options for handling a wallet verification challenge
820
820
 
821
821
  | Property | Type | Description | Defined in |
822
822
  | ------ | ------ | ------ | ------ |
823
- | <a id="code"></a> `code` | `string` \| `number` | The verification code provided by the user | [sdk/portal/src/utils/wallet-verification-challenge.ts:74](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wallet-verification-challenge.ts#L74) |
824
- | <a id="portalclient"></a> `portalClient` | `GraphQLClient` | The portal client instance | [sdk/portal/src/utils/wallet-verification-challenge.ts:66](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wallet-verification-challenge.ts#L66) |
825
- | <a id="portalgraphql"></a> `portalGraphql` | `initGraphQLTada`\<`Setup`\> | The GraphQL query builder | [sdk/portal/src/utils/wallet-verification-challenge.ts:68](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wallet-verification-challenge.ts#L68) |
826
- | <a id="userwalletaddress"></a> `userWalletAddress` | `` `0x${string}` `` | The wallet address to verify | [sdk/portal/src/utils/wallet-verification-challenge.ts:72](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wallet-verification-challenge.ts#L72) |
827
- | <a id="verificationid"></a> `verificationId` | `string` | The ID of the verification challenge | [sdk/portal/src/utils/wallet-verification-challenge.ts:70](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wallet-verification-challenge.ts#L70) |
828
- | <a id="verificationtype"></a> `verificationType` | `"otp"` \| `"secret-code"` \| `"pincode"` | The type of verification being performed | [sdk/portal/src/utils/wallet-verification-challenge.ts:76](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wallet-verification-challenge.ts#L76) |
823
+ | <a id="code"></a> `code` | `string` \| `number` | The verification code provided by the user | [sdk/portal/src/utils/wallet-verification-challenge.ts:74](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wallet-verification-challenge.ts#L74) |
824
+ | <a id="portalclient"></a> `portalClient` | `GraphQLClient` | The portal client instance | [sdk/portal/src/utils/wallet-verification-challenge.ts:66](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wallet-verification-challenge.ts#L66) |
825
+ | <a id="portalgraphql"></a> `portalGraphql` | `initGraphQLTada`\<`Setup`\> | The GraphQL query builder | [sdk/portal/src/utils/wallet-verification-challenge.ts:68](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wallet-verification-challenge.ts#L68) |
826
+ | <a id="userwalletaddress"></a> `userWalletAddress` | `` `0x${string}` `` | The wallet address to verify | [sdk/portal/src/utils/wallet-verification-challenge.ts:72](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wallet-verification-challenge.ts#L72) |
827
+ | <a id="verificationid"></a> `verificationId` | `string` | The ID of the verification challenge | [sdk/portal/src/utils/wallet-verification-challenge.ts:70](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wallet-verification-challenge.ts#L70) |
828
+ | <a id="verificationtype"></a> `verificationType` | `"otp"` \| `"secret-code"` \| `"pincode"` | The type of verification being performed | [sdk/portal/src/utils/wallet-verification-challenge.ts:76](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wallet-verification-challenge.ts#L76) |
829
829
 
830
830
  ***
831
831
 
832
832
  #### Transaction
833
833
 
834
- Defined in: [sdk/portal/src/utils/wait-for-transaction-receipt.ts:34](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L34)
834
+ Defined in: [sdk/portal/src/utils/wait-for-transaction-receipt.ts:34](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L34)
835
835
 
836
836
  Represents the structure of a blockchain transaction with its receipt
837
837
 
@@ -839,18 +839,18 @@ Represents the structure of a blockchain transaction with its receipt
839
839
 
840
840
  | Property | Type | Description | Defined in |
841
841
  | ------ | ------ | ------ | ------ |
842
- | <a id="address"></a> `address` | `string` | The contract address involved in the transaction | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:43](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L43) |
843
- | <a id="createdat"></a> `createdAt` | `string` | Timestamp when the transaction was created | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:41](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L41) |
844
- | <a id="from"></a> `from` | `string` | The sender address (duplicate of receipt.from) | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:39](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L39) |
845
- | <a id="functionname"></a> `functionName` | `string` | The name of the function called in the transaction | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:45](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L45) |
846
- | <a id="iscontract"></a> `isContract` | `boolean` | Whether the transaction is a contract deployment | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:47](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L47) |
847
- | <a id="transactionhash"></a> `transactionHash` | `string` | The hash of the transaction (duplicate of receipt.transactionHash) | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:37](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L37) |
842
+ | <a id="address"></a> `address` | `string` | The contract address involved in the transaction | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:43](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L43) |
843
+ | <a id="createdat"></a> `createdAt` | `string` | Timestamp when the transaction was created | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:41](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L41) |
844
+ | <a id="from"></a> `from` | `string` | The sender address (duplicate of receipt.from) | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:39](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L39) |
845
+ | <a id="functionname"></a> `functionName` | `string` | The name of the function called in the transaction | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:45](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L45) |
846
+ | <a id="iscontract"></a> `isContract` | `boolean` | Whether the transaction is a contract deployment | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:47](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L47) |
847
+ | <a id="transactionhash"></a> `transactionHash` | `string` | The hash of the transaction (duplicate of receipt.transactionHash) | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:37](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L37) |
848
848
 
849
849
  ***
850
850
 
851
851
  #### TransactionEvent
852
852
 
853
- Defined in: [sdk/portal/src/utils/wait-for-transaction-receipt.ts:8](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L8)
853
+ Defined in: [sdk/portal/src/utils/wait-for-transaction-receipt.ts:8](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L8)
854
854
 
855
855
  Represents an event emitted during a transaction execution
856
856
 
@@ -858,15 +858,15 @@ Represents an event emitted during a transaction execution
858
858
 
859
859
  | Property | Type | Description | Defined in |
860
860
  | ------ | ------ | ------ | ------ |
861
- | <a id="args"></a> `args` | `Record`\<`string`, `unknown`\> | The arguments emitted by the event | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:12](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L12) |
862
- | <a id="eventname"></a> `eventName` | `string` | The name of the event that was emitted | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:10](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L10) |
863
- | <a id="topics"></a> `topics` | `` `0x${string}` ``[] | Indexed event parameters used for filtering and searching | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:14](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L14) |
861
+ | <a id="args"></a> `args` | `Record`\<`string`, `unknown`\> | The arguments emitted by the event | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:12](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L12) |
862
+ | <a id="eventname"></a> `eventName` | `string` | The name of the event that was emitted | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:10](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L10) |
863
+ | <a id="topics"></a> `topics` | `` `0x${string}` ``[] | Indexed event parameters used for filtering and searching | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:14](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L14) |
864
864
 
865
865
  ***
866
866
 
867
867
  #### TransactionReceipt
868
868
 
869
- Defined in: [sdk/portal/src/utils/wait-for-transaction-receipt.ts:20](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L20)
869
+ Defined in: [sdk/portal/src/utils/wait-for-transaction-receipt.ts:20](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L20)
870
870
 
871
871
  Represents the structure of a blockchain transaction receipt
872
872
 
@@ -878,16 +878,16 @@ Represents the structure of a blockchain transaction receipt
878
878
 
879
879
  | Property | Type | Description | Overrides | Defined in |
880
880
  | ------ | ------ | ------ | ------ | ------ |
881
- | <a id="contractaddress"></a> `contractAddress` | `` `0x${string}` `` | The address of the contract deployed in the transaction | `TransactionReceiptViem.contractAddress` | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:28](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L28) |
882
- | <a id="events"></a> `events` | [`TransactionEvent`](#transactionevent)[] | Array of events emitted during the transaction | - | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:26](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L26) |
883
- | <a id="revertreason"></a> `revertReason` | `string` | The raw reason for transaction reversion, if applicable | - | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:22](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L22) |
884
- | <a id="revertreasondecoded"></a> `revertReasonDecoded` | `string` | Human-readable version of the revert reason | - | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:24](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L24) |
881
+ | <a id="contractaddress"></a> `contractAddress` | `` `0x${string}` `` | The address of the contract deployed in the transaction | `TransactionReceiptViem.contractAddress` | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:28](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L28) |
882
+ | <a id="events"></a> `events` | [`TransactionEvent`](#transactionevent)[] | Array of events emitted during the transaction | - | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:26](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L26) |
883
+ | <a id="revertreason"></a> `revertReason` | `string` | The raw reason for transaction reversion, if applicable | - | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:22](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L22) |
884
+ | <a id="revertreasondecoded"></a> `revertReasonDecoded` | `string` | Human-readable version of the revert reason | - | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:24](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L24) |
885
885
 
886
886
  ***
887
887
 
888
888
  #### WaitForTransactionReceiptOptions
889
889
 
890
- Defined in: [sdk/portal/src/utils/wait-for-transaction-receipt.ts:57](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L57)
890
+ Defined in: [sdk/portal/src/utils/wait-for-transaction-receipt.ts:57](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L57)
891
891
 
892
892
  Options for waiting for a transaction receipt
893
893
 
@@ -899,15 +899,15 @@ Options for waiting for a transaction receipt
899
899
 
900
900
  | Property | Type | Description | Inherited from | Defined in |
901
901
  | ------ | ------ | ------ | ------ | ------ |
902
- | <a id="accesstoken"></a> `accessToken?` | `string` | The access token for authentication with the Portal API | [`WebsocketClientOptions`](#websocketclientoptions).[`accessToken`](#accesstoken-1) | [sdk/portal/src/utils/websocket-client.ts:14](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/websocket-client.ts#L14) |
903
- | <a id="portalgraphqlendpoint"></a> `portalGraphqlEndpoint` | `string` | The GraphQL endpoint URL for the Portal API | [`WebsocketClientOptions`](#websocketclientoptions).[`portalGraphqlEndpoint`](#portalgraphqlendpoint-1) | [sdk/portal/src/utils/websocket-client.ts:10](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/websocket-client.ts#L10) |
904
- | <a id="timeout"></a> `timeout?` | `number` | Optional timeout in milliseconds before the operation fails | - | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:59](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L59) |
902
+ | <a id="accesstoken"></a> `accessToken?` | `string` | The access token for authentication with the Portal API | [`WebsocketClientOptions`](#websocketclientoptions).[`accessToken`](#accesstoken-1) | [sdk/portal/src/utils/websocket-client.ts:14](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/websocket-client.ts#L14) |
903
+ | <a id="portalgraphqlendpoint"></a> `portalGraphqlEndpoint` | `string` | The GraphQL endpoint URL for the Portal API | [`WebsocketClientOptions`](#websocketclientoptions).[`portalGraphqlEndpoint`](#portalgraphqlendpoint-1) | [sdk/portal/src/utils/websocket-client.ts:10](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/websocket-client.ts#L10) |
904
+ | <a id="timeout"></a> `timeout?` | `number` | Optional timeout in milliseconds before the operation fails | - | [sdk/portal/src/utils/wait-for-transaction-receipt.ts:59](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/wait-for-transaction-receipt.ts#L59) |
905
905
 
906
906
  ***
907
907
 
908
908
  #### WebsocketClientOptions
909
909
 
910
- Defined in: [sdk/portal/src/utils/websocket-client.ts:6](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/websocket-client.ts#L6)
910
+ Defined in: [sdk/portal/src/utils/websocket-client.ts:6](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/websocket-client.ts#L6)
911
911
 
912
912
  Options for the GraphQL WebSocket client
913
913
 
@@ -919,8 +919,8 @@ Options for the GraphQL WebSocket client
919
919
 
920
920
  | Property | Type | Description | Defined in |
921
921
  | ------ | ------ | ------ | ------ |
922
- | <a id="accesstoken-1"></a> `accessToken?` | `string` | The access token for authentication with the Portal API | [sdk/portal/src/utils/websocket-client.ts:14](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/websocket-client.ts#L14) |
923
- | <a id="portalgraphqlendpoint-1"></a> `portalGraphqlEndpoint` | `string` | The GraphQL endpoint URL for the Portal API | [sdk/portal/src/utils/websocket-client.ts:10](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/utils/websocket-client.ts#L10) |
922
+ | <a id="accesstoken-1"></a> `accessToken?` | `string` | The access token for authentication with the Portal API | [sdk/portal/src/utils/websocket-client.ts:14](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/websocket-client.ts#L14) |
923
+ | <a id="portalgraphqlendpoint-1"></a> `portalGraphqlEndpoint` | `string` | The GraphQL endpoint URL for the Portal API | [sdk/portal/src/utils/websocket-client.ts:10](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/utils/websocket-client.ts#L10) |
924
924
 
925
925
  ### Type Aliases
926
926
 
@@ -928,7 +928,7 @@ Options for the GraphQL WebSocket client
928
928
 
929
929
  > **ClientOptions** = `object`
930
930
 
931
- Defined in: [sdk/portal/src/portal.ts:25](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/portal.ts#L25)
931
+ Defined in: [sdk/portal/src/portal.ts:25](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/portal.ts#L25)
932
932
 
933
933
  Type representing the validated client options.
934
934
 
@@ -936,9 +936,9 @@ Type representing the validated client options.
936
936
 
937
937
  | Name | Type | Default value | Defined in |
938
938
  | ------ | ------ | ------ | ------ |
939
- | <a id="accesstoken-2"></a> `accessToken?` | `string` | - | [sdk/portal/src/portal.ts:18](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/portal.ts#L18) |
940
- | <a id="cache"></a> `cache?` | `"default"` \| `"force-cache"` \| `"no-cache"` \| `"no-store"` \| `"only-if-cached"` \| `"reload"` | - | [sdk/portal/src/portal.ts:19](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/portal.ts#L19) |
941
- | <a id="instance"></a> `instance` | `string` | `UrlOrPathSchema` | [sdk/portal/src/portal.ts:17](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/portal.ts#L17) |
939
+ | <a id="accesstoken-2"></a> `accessToken?` | `string` | - | [sdk/portal/src/portal.ts:18](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/portal.ts#L18) |
940
+ | <a id="cache"></a> `cache?` | `"default"` \| `"force-cache"` \| `"no-cache"` \| `"no-store"` \| `"only-if-cached"` \| `"reload"` | - | [sdk/portal/src/portal.ts:19](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/portal.ts#L19) |
941
+ | <a id="instance"></a> `instance` | `string` | `UrlOrPathSchema` | [sdk/portal/src/portal.ts:17](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/portal.ts#L17) |
942
942
 
943
943
  ***
944
944
 
@@ -946,7 +946,7 @@ Type representing the validated client options.
946
946
 
947
947
  > **RequestConfig** = `ConstructorParameters`\<*typeof* `GraphQLClient`\>\[`1`\]
948
948
 
949
- Defined in: [sdk/portal/src/portal.ts:11](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/portal.ts#L11)
949
+ Defined in: [sdk/portal/src/portal.ts:11](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/portal.ts#L11)
950
950
 
951
951
  Configuration options for the GraphQL client, excluding 'url' and 'exchanges'.
952
952
 
@@ -956,7 +956,7 @@ Configuration options for the GraphQL client, excluding 'url' and 'exchanges'.
956
956
 
957
957
  > `const` **ClientOptionsSchema**: `ZodObject`\<[`ClientOptions`](#clientoptions)\>
958
958
 
959
- Defined in: [sdk/portal/src/portal.ts:16](https://github.com/settlemint/sdk/blob/v2.5.13/sdk/portal/src/portal.ts#L16)
959
+ Defined in: [sdk/portal/src/portal.ts:16](https://github.com/settlemint/sdk/blob/v2.5.14/sdk/portal/src/portal.ts#L16)
960
960
 
961
961
  Schema for validating Portal client configuration options.
962
962
 
@@ -108,10 +108,14 @@ interface WaitForTransactionReceiptOptions extends WebsocketClientOptions {
108
108
  declare function waitForTransactionReceipt(transactionHash: string, options: WaitForTransactionReceiptOptions): Promise<Transaction>;
109
109
  //#endregion
110
110
  //#region src/utils/wallet-verification-challenge.d.ts
111
+ /**
112
+ * Type representing the different types of wallet verification methods
113
+ */
114
+ type WalletVerificationType = "PINCODE" | "OTP" | "SECRET_CODES";
111
115
  /**
112
116
  * Custom error class for challenge-related errors
113
117
  */
114
- declare class ChallengeError extends Error {
118
+ declare class WalletVerificationChallengeError extends Error {
115
119
  readonly code: string;
116
120
  constructor(message: string, code: string);
117
121
  }
@@ -130,14 +134,16 @@ interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSc
130
134
  /** The verification code provided by the user */
131
135
  code: string | number;
132
136
  /** The type of verification being performed */
133
- verificationType: "otp" | "secret-code" | "pincode";
137
+ verificationType: WalletVerificationType;
138
+ /** Request id which can be added for tracing purposes */
139
+ requestId?: string;
134
140
  }
135
141
  /**
136
142
  * Handles a wallet verification challenge by generating an appropriate response
137
143
  *
138
144
  * @param options - The options for handling the wallet verification challenge
139
145
  * @returns Promise resolving to an object containing the challenge response and optionally the verification ID
140
- * @throws {ChallengeError} If the challenge cannot be created or is invalid
146
+ * @throws {WalletVerificationChallengeError} If the challenge cannot be created or is invalid
141
147
  * @example
142
148
  * import { createPortalClient } from "@settlemint/sdk-portal";
143
149
  * import { handleWalletVerificationChallenge } from "@settlemint/sdk-portal";
@@ -153,7 +159,7 @@ interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSc
153
159
  * verificationId: "verification-123",
154
160
  * userWalletAddress: "0x123...",
155
161
  * code: "123456",
156
- * verificationType: "otp"
162
+ * verificationType: "OTP"
157
163
  * });
158
164
  */
159
165
  declare function handleWalletVerificationChallenge<const Setup extends AbstractSetupSchema>({
@@ -162,10 +168,11 @@ declare function handleWalletVerificationChallenge<const Setup extends AbstractS
162
168
  verificationId,
163
169
  userWalletAddress,
164
170
  code,
165
- verificationType
171
+ verificationType,
172
+ requestId
166
173
  }: HandleWalletVerificationChallengeOptions<Setup>): Promise<{
167
174
  challengeResponse: string;
168
- verificationId?: string;
175
+ challengeId: string;
169
176
  }>;
170
177
  //#endregion
171
178
  //#region src/portal.d.ts
@@ -242,5 +249,5 @@ declare function createPortalClient<const Setup extends AbstractSetupSchema>(opt
242
249
  graphql: initGraphQLTada<Setup>;
243
250
  };
244
251
  //#endregion
245
- export { ClientOptions, ClientOptionsSchema, type FragmentOf, type HandleWalletVerificationChallengeOptions, RequestConfig, type ResultOf, type Transaction, type TransactionEvent, type TransactionReceipt, type VariablesOf, type WaitForTransactionReceiptOptions, type WebsocketClientOptions, createPortalClient, getWebsocketClient, handleWalletVerificationChallenge, readFragment, waitForTransactionReceipt };
252
+ export { ClientOptions, ClientOptionsSchema, type FragmentOf, type HandleWalletVerificationChallengeOptions, RequestConfig, type ResultOf, type Transaction, type TransactionEvent, type TransactionReceipt, type VariablesOf, type WaitForTransactionReceiptOptions, WalletVerificationChallengeError, type WalletVerificationType, type WebsocketClientOptions, createPortalClient, getWebsocketClient, handleWalletVerificationChallenge, readFragment, waitForTransactionReceipt };
246
253
  //# sourceMappingURL=portal.d.ts.map
@@ -113,7 +113,7 @@ async function getTransactionFromSubscription(subscription) {
113
113
  /**
114
114
  * Custom error class for challenge-related errors
115
115
  */
116
- var ChallengeError = class extends Error {
116
+ var WalletVerificationChallengeError = class extends Error {
117
117
  code;
118
118
  constructor(message, code) {
119
119
  super(message);
@@ -146,7 +146,7 @@ function generateResponse(pincode, salt, challenge) {
146
146
  *
147
147
  * @param options - The options for handling the wallet verification challenge
148
148
  * @returns Promise resolving to an object containing the challenge response and optionally the verification ID
149
- * @throws {ChallengeError} If the challenge cannot be created or is invalid
149
+ * @throws {WalletVerificationChallengeError} If the challenge cannot be created or is invalid
150
150
  * @example
151
151
  * import { createPortalClient } from "@settlemint/sdk-portal";
152
152
  * import { handleWalletVerificationChallenge } from "@settlemint/sdk-portal";
@@ -162,55 +162,65 @@ function generateResponse(pincode, salt, challenge) {
162
162
  * verificationId: "verification-123",
163
163
  * userWalletAddress: "0x123...",
164
164
  * code: "123456",
165
- * verificationType: "otp"
165
+ * verificationType: "OTP"
166
166
  * });
167
167
  */
168
- async function handleWalletVerificationChallenge({ portalClient, portalGraphql, verificationId, userWalletAddress, code, verificationType }) {
168
+ async function handleWalletVerificationChallenge({ portalClient, portalGraphql, verificationId, userWalletAddress, code, verificationType, requestId }) {
169
169
  try {
170
- if (verificationType === "otp") {
171
- return {
172
- challengeResponse: code.toString(),
173
- verificationId
174
- };
170
+ const requestHeaders = new Headers();
171
+ if (requestId) {
172
+ requestHeaders.append("x-request-id", requestId);
175
173
  }
176
- if (verificationType === "secret-code") {
177
- const formattedCode = code.toString().replace(/(.{5})(?=.)/, "$1-");
178
- return {
179
- challengeResponse: formattedCode,
180
- verificationId
181
- };
182
- }
183
- const verificationChallenges = await portalClient.request(portalGraphql(`
184
- mutation CreateWalletVerificationChallenges($userWalletAddress: String!, $verificationId: String!) {
185
- createWalletVerificationChallenges(userWalletAddress: $userWalletAddress, verificationId: $verificationId) {
186
- challenge
174
+ const verificationChallenge = await portalClient.request(portalGraphql(`
175
+ mutation CreateWalletVerificationChallenge($userWalletAddress: String!, $verificationId: String!) {
176
+ createWalletVerificationChallenge(
177
+ userWalletAddress: $userWalletAddress
178
+ verificationId: $verificationId
179
+ ) {
187
180
  id
188
181
  name
182
+ verificationId
189
183
  verificationType
184
+ challenge {
185
+ salt
186
+ secret
187
+ }
190
188
  }
191
189
  }
192
190
  `), {
193
191
  userWalletAddress,
194
192
  verificationId
195
- });
196
- if (!verificationChallenges.createWalletVerificationChallenges?.length) {
197
- throw new ChallengeError("No verification challenges received", "NO_CHALLENGES");
193
+ }, requestHeaders);
194
+ if (!verificationChallenge.createWalletVerificationChallenge) {
195
+ throw new WalletVerificationChallengeError("No verification challenge received", "NO_CHALLENGES");
196
+ }
197
+ if (verificationType === "OTP") {
198
+ return {
199
+ challengeResponse: code.toString(),
200
+ challengeId: verificationChallenge.createWalletVerificationChallenge.id
201
+ };
198
202
  }
199
- const walletVerificationChallenge = verificationChallenges.createWalletVerificationChallenges.find((challenge) => challenge.id === verificationId);
200
- if (!walletVerificationChallenge?.challenge?.secret || !walletVerificationChallenge?.challenge?.salt) {
201
- throw new ChallengeError("Invalid challenge format", "INVALID_CHALLENGE");
203
+ if (verificationType === "SECRET_CODES") {
204
+ const formattedCode = code.toString().replace(/(.{5})(?=.)/, "$1-");
205
+ return {
206
+ challengeResponse: formattedCode,
207
+ challengeId: verificationChallenge.createWalletVerificationChallenge.id
208
+ };
209
+ }
210
+ const { secret, salt } = verificationChallenge.createWalletVerificationChallenge.challenge ?? {};
211
+ if (!secret || !salt) {
212
+ throw new WalletVerificationChallengeError("Invalid challenge format", "INVALID_CHALLENGE");
202
213
  }
203
- const { secret, salt } = walletVerificationChallenge.challenge;
204
214
  const challengeResponse = generateResponse(code.toString(), salt, secret);
205
215
  return {
206
216
  challengeResponse,
207
- verificationId
217
+ challengeId: verificationChallenge.createWalletVerificationChallenge.id
208
218
  };
209
219
  } catch (error) {
210
- if (error instanceof ChallengeError) {
220
+ if (error instanceof WalletVerificationChallengeError) {
211
221
  throw error;
212
222
  }
213
- throw new ChallengeError("Failed to process wallet verification challenge", "CHALLENGE_PROCESSING_ERROR");
223
+ throw new WalletVerificationChallengeError("Failed to process wallet verification challenge", "CHALLENGE_PROCESSING_ERROR");
214
224
  }
215
225
  }
216
226
 
@@ -291,5 +301,5 @@ function createPortalClient(options, clientOptions) {
291
301
  }
292
302
 
293
303
  //#endregion
294
- export { ClientOptionsSchema, createPortalClient, getWebsocketClient, handleWalletVerificationChallenge, readFragment, waitForTransactionReceipt };
304
+ export { ClientOptionsSchema, WalletVerificationChallengeError, createPortalClient, getWebsocketClient, handleWalletVerificationChallenge, readFragment, waitForTransactionReceipt };
295
305
  //# sourceMappingURL=portal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"portal.js","names":["url: URL","transactionHash: string","options: WaitForTransactionReceiptOptions","timeout: number","subscription: AsyncIterableIterator<FormattedExecutionResult<GetTransactionResponse, unknown>>","message: string","code: string","pincode: string","salt: string","challenge: string","options: ClientOptions","clientOptions?: RequestConfig"],"sources":["../../src/utils/websocket-client.ts","../../src/utils/wait-for-transaction-receipt.ts","../../src/utils/wallet-verification-challenge.ts","../../src/portal.ts"],"sourcesContent":["import { createClient } from \"graphql-ws\";\n\n/**\n * Options for the GraphQL WebSocket client\n */\nexport interface WebsocketClientOptions {\n /**\n * The GraphQL endpoint URL for the Portal API\n */\n portalGraphqlEndpoint: string;\n /**\n * The access token for authentication with the Portal API\n */\n accessToken?: string;\n}\n\n/**\n * Creates a GraphQL WebSocket client for the Portal API\n *\n * @param {WebsocketClientOptions} options - The options for the client\n * @returns {Client} The GraphQL WebSocket client\n * @example\n * import { getWebsocketClient } from \"@settlemint/sdk-portal\";\n *\n * const client = getWebsocketClient({\n * portalGraphqlEndpoint: \"https://portal.settlemint.com/graphql\",\n * accessToken: \"your-access-token\",\n * });\n */\nexport function getWebsocketClient({ portalGraphqlEndpoint, accessToken }: WebsocketClientOptions) {\n if (!portalGraphqlEndpoint) {\n throw new Error(\"portalGraphqlEndpoint is required\");\n }\n const graphqlEndpoint = setWsProtocol(new URL(portalGraphqlEndpoint));\n return createClient({\n url: accessToken\n ? `${graphqlEndpoint.protocol}//${graphqlEndpoint.host}/${accessToken}${graphqlEndpoint.pathname}${graphqlEndpoint.search}`\n : graphqlEndpoint.toString(),\n });\n}\n\nfunction setWsProtocol(url: URL) {\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n return url;\n }\n if (url.protocol === \"http:\") {\n url.protocol = \"ws:\";\n } else {\n url.protocol = \"wss:\";\n }\n return url;\n}\n","import type { FormattedExecutionResult } from \"graphql-ws\";\nimport type { Address, Hex, TransactionReceipt as TransactionReceiptViem } from \"viem\";\nimport { type WebsocketClientOptions, getWebsocketClient } from \"./websocket-client.js\";\n\n/**\n * Represents an event emitted during a transaction execution\n */\nexport interface TransactionEvent {\n /** The name of the event that was emitted */\n eventName: string;\n /** The arguments emitted by the event */\n args: Record<string, unknown>;\n /** Indexed event parameters used for filtering and searching */\n topics: Hex[];\n}\n\n/**\n * Represents the structure of a blockchain transaction receipt\n */\nexport interface TransactionReceipt extends TransactionReceiptViem<string, number, \"Success\" | \"Reverted\"> {\n /** The raw reason for transaction reversion, if applicable */\n revertReason: string;\n /** Human-readable version of the revert reason */\n revertReasonDecoded: string;\n /** Array of events emitted during the transaction */\n events: TransactionEvent[];\n /** The address of the contract deployed in the transaction */\n contractAddress: Address;\n}\n\n/**\n * Represents the structure of a blockchain transaction with its receipt\n */\nexport interface Transaction {\n receipt: TransactionReceipt;\n /** The hash of the transaction (duplicate of receipt.transactionHash) */\n transactionHash: string;\n /** The sender address (duplicate of receipt.from) */\n from: string;\n /** Timestamp when the transaction was created */\n createdAt: string;\n /** The contract address involved in the transaction */\n address: string;\n /** The name of the function called in the transaction */\n functionName: string;\n /** Whether the transaction is a contract deployment */\n isContract: boolean;\n}\n\ninterface GetTransactionResponse {\n getTransaction: Transaction;\n}\n\n/**\n * Options for waiting for a transaction receipt\n */\nexport interface WaitForTransactionReceiptOptions extends WebsocketClientOptions {\n /** Optional timeout in milliseconds before the operation fails */\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 = getWebsocketClient(options);\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","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 */\nexport interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSchema> {\n /** The portal client instance */\n portalClient: GraphQLClient;\n /** The GraphQL query builder */\n portalGraphql: initGraphQLTada<Setup>;\n /** The ID of the verification challenge */\n verificationId: string;\n /** The wallet address to verify */\n userWalletAddress: Address;\n /** The verification code provided by the user */\n code: string | number;\n /** The type of verification being performed */\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 { appendHeaders } from \"@settlemint/sdk-utils/http\";\nimport { 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.optional(),\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: appendHeaders(clientOptions?.headers, { \"x-auth-token\": validatedOptions.accessToken }),\n }),\n graphql,\n };\n}\n\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport { readFragment } from \"gql.tada\";\nexport {\n type Transaction,\n type TransactionEvent,\n type TransactionReceipt,\n type WaitForTransactionReceiptOptions,\n waitForTransactionReceipt,\n} from \"./utils/wait-for-transaction-receipt.js\";\nexport {\n type HandleWalletVerificationChallengeOptions,\n handleWalletVerificationChallenge,\n} from \"./utils/wallet-verification-challenge.js\";\nexport { getWebsocketClient, type WebsocketClientOptions } from \"./utils/websocket-client.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAgB,mBAAmB,EAAE,uBAAuB,aAAqC,EAAE;AACjG,KAAI,CAAC,uBAAuB;AAC1B,QAAM,IAAI,MAAM;CACjB;CACD,MAAM,kBAAkB,cAAc,IAAI,IAAI,uBAAuB;AACrE,QAAO,aAAa,EAClB,KAAK,cACD,GAAG,gBAAgB,SAAS,EAAE,EAAE,gBAAgB,KAAK,CAAC,EAAE,cAAc,gBAAgB,WAAW,gBAAgB,QAAQ,GACzH,gBAAgB,UAAU,CAC/B,EAAC;AACH;AAED,SAAS,cAAcA,KAAU;AAC/B,KAAI,IAAI,aAAa,SAAS,IAAI,aAAa,QAAQ;AACrD,SAAO;CACR;AACD,KAAI,IAAI,aAAa,SAAS;EAC5B,IAAI,WAAW;CAChB,OAAM;EACL,IAAI,WAAW;CAChB;AACD,QAAO;AACR;;;;;;;;;;;;;;;;;;;;;;AC4BD,eAAsB,0BAA0BC,iBAAyBC,SAA2C;CAClH,MAAM,WAAW,mBAAmB,QAAQ;CAC5C,MAAM,eAAe,SAAS,QAAgC;EAC5D,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;OAqBL,CAAC;EACJ,WAAW,EAAE,gBAAiB;CAC/B,EAAC;CACF,MAAM,WAAW,CAAC,+BAA+B,aAAa,AAAC;AAC/D,KAAI,QAAQ,SAAS;EACnB,SAAS,KAAK,qBAAqB,QAAQ,QAAQ,CAAC;CACrD;AAED,QAAO,QAAQ,KAAK,SAAS;AAC9B;AAED,SAAS,qBAAqBC,SAAiC;AAC7D,QAAO,IAAI,QAAQ,CAAC,GAAG,WAAW;EAChC,WAAW,MAAM,OAAO,IAAI,MAAM,iCAAiC,EAAE,QAAQ;CAC9E;AACF;AAED,eAAe,+BACbC,cACsB;AACtB,YAAW,MAAM,UAAU,cAAc;AACvC,MAAI,QAAQ,MAAM,gBAAgB,SAAS;AACzC,UAAO,OAAO,KAAK;EACpB;CACF;AACD,OAAM,IAAI,MAAM;AACjB;;;;;;;ACzHD,IAAa,iBAAb,cAAoC,MAAM;CACxC,AAAS;CAET,YAAYC,SAAiBC,MAAc;EACzC,MAAM,QAAQ;EACd,KAAK,OAAO;EACZ,KAAK,OAAO;CACb;AACF;;;;;;;AA4BD,SAAS,YAAYC,SAAiBC,MAAsB;AAC1D,QAAO,WAAW,SAAS,CAAC,OAAO,GAAG,OAAO,SAAS,CAAC,CAAC,OAAO,MAAM;AACtE;;;;;;;;AASD,SAAS,iBAAiBD,SAAiBC,MAAcC,WAA2B;CAClF,MAAM,gBAAgB,YAAY,SAAS,KAAK;AAChD,QAAO,WAAW,SAAS,CAAC,OAAO,GAAG,cAAc,CAAC,EAAE,WAAW,CAAC,CAAC,OAAO,MAAM;AAClF;;;;;;;;;;;;;;;;;;;;;;;;;AA4CD,eAAsB,kCAA2E,EAC/F,cACA,eACA,gBACA,mBACA,MACA,kBACgD,EAG/C;AACD,KAAI;AACF,MAAI,qBAAqB,OAAO;AAC9B,UAAO;IACL,mBAAmB,KAAK,UAAU;IAClC;GACD;EACF;AAED,MAAI,qBAAqB,eAAe;GAEtC,MAAM,gBAAgB,KAAK,UAAU,CAAC,QAAQ,eAAe,MAAM;AACnE,UAAO;IACL,mBAAmB;IACnB;GACD;EACF;EAED,MAAM,yBAAyB,MAAM,aAAa,QAChD,cAAc,CAAC;;;;;;;;;MASf,CAAC,CAAC,EACF;GACE;GACA;EACD,EACF;AAED,MAAI,CAAC,uBAAuB,oCAAoC,QAAQ;AACtE,SAAM,IAAI,eAAe,uCAAuC;EACjE;EAED,MAAM,8BAA8B,uBAAuB,mCAAmC,KAC5F,CAAC,cAAc,UAAU,OAAO,eACjC;AAED,MAAI,CAAC,6BAA6B,WAAW,UAAU,CAAC,6BAA6B,WAAW,MAAM;AACpG,SAAM,IAAI,eAAe,4BAA4B;EACtD;EAED,MAAM,EAAE,QAAQ,MAAM,GAAG,4BAA4B;EACrD,MAAM,oBAAoB,iBAAiB,KAAK,UAAU,EAAE,MAAM,OAAO;AACzE,SAAO;GACL;GACA;EACD;CACF,SAAQ,OAAO;AACd,MAAI,iBAAiB,gBAAgB;AACnC,SAAM;EACP;AACD,QAAM,IAAI,eAAe,mDAAmD;CAC7E;AACF;;;;;;;AC5JD,MAAa,sBAAsB,EAAE,OAAO;CAC1C,UAAU;CACV,aAAa,6BAA6B,UAAU;CACpD,OAAO,EAAE,KAAK;EAAC;EAAW;EAAe;EAAY;EAAY;EAAkB;CAAS,EAAC,CAAC,UAAU;AACzG,EAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDF,SAAgB,mBACdC,SACAC,eAIA;CACA,cAAc;CACd,MAAM,mBAAmB,SAAS,qBAAqB,QAAQ;CAC/D,MAAM,UAAU,iBAAwB;CACxC,MAAM,UAAU,IAAI,IAAI,iBAAiB,UAAU,UAAU;AAE7D,QAAO;EACL,QAAQ,IAAI,cAAc,SAAS;GACjC,GAAG;GACH,SAAS,cAAc,eAAe,SAAS,EAAE,gBAAgB,iBAAiB,YAAa,EAAC;EACjG;EACD;CACD;AACF"}
1
+ {"version":3,"file":"portal.js","names":["url: URL","transactionHash: string","options: WaitForTransactionReceiptOptions","timeout: number","subscription: AsyncIterableIterator<FormattedExecutionResult<GetTransactionResponse, unknown>>","message: string","code: string","pincode: string","salt: string","challenge: string","options: ClientOptions","clientOptions?: RequestConfig"],"sources":["../../src/utils/websocket-client.ts","../../src/utils/wait-for-transaction-receipt.ts","../../src/utils/wallet-verification-challenge.ts","../../src/portal.ts"],"sourcesContent":["import { createClient } from \"graphql-ws\";\n\n/**\n * Options for the GraphQL WebSocket client\n */\nexport interface WebsocketClientOptions {\n /**\n * The GraphQL endpoint URL for the Portal API\n */\n portalGraphqlEndpoint: string;\n /**\n * The access token for authentication with the Portal API\n */\n accessToken?: string;\n}\n\n/**\n * Creates a GraphQL WebSocket client for the Portal API\n *\n * @param {WebsocketClientOptions} options - The options for the client\n * @returns {Client} The GraphQL WebSocket client\n * @example\n * import { getWebsocketClient } from \"@settlemint/sdk-portal\";\n *\n * const client = getWebsocketClient({\n * portalGraphqlEndpoint: \"https://portal.settlemint.com/graphql\",\n * accessToken: \"your-access-token\",\n * });\n */\nexport function getWebsocketClient({ portalGraphqlEndpoint, accessToken }: WebsocketClientOptions) {\n if (!portalGraphqlEndpoint) {\n throw new Error(\"portalGraphqlEndpoint is required\");\n }\n const graphqlEndpoint = setWsProtocol(new URL(portalGraphqlEndpoint));\n return createClient({\n url: accessToken\n ? `${graphqlEndpoint.protocol}//${graphqlEndpoint.host}/${accessToken}${graphqlEndpoint.pathname}${graphqlEndpoint.search}`\n : graphqlEndpoint.toString(),\n });\n}\n\nfunction setWsProtocol(url: URL) {\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n return url;\n }\n if (url.protocol === \"http:\") {\n url.protocol = \"ws:\";\n } else {\n url.protocol = \"wss:\";\n }\n return url;\n}\n","import type { FormattedExecutionResult } from \"graphql-ws\";\nimport type { Address, Hex, TransactionReceipt as TransactionReceiptViem } from \"viem\";\nimport { type WebsocketClientOptions, getWebsocketClient } from \"./websocket-client.js\";\n\n/**\n * Represents an event emitted during a transaction execution\n */\nexport interface TransactionEvent {\n /** The name of the event that was emitted */\n eventName: string;\n /** The arguments emitted by the event */\n args: Record<string, unknown>;\n /** Indexed event parameters used for filtering and searching */\n topics: Hex[];\n}\n\n/**\n * Represents the structure of a blockchain transaction receipt\n */\nexport interface TransactionReceipt extends TransactionReceiptViem<string, number, \"Success\" | \"Reverted\"> {\n /** The raw reason for transaction reversion, if applicable */\n revertReason: string;\n /** Human-readable version of the revert reason */\n revertReasonDecoded: string;\n /** Array of events emitted during the transaction */\n events: TransactionEvent[];\n /** The address of the contract deployed in the transaction */\n contractAddress: Address;\n}\n\n/**\n * Represents the structure of a blockchain transaction with its receipt\n */\nexport interface Transaction {\n receipt: TransactionReceipt;\n /** The hash of the transaction (duplicate of receipt.transactionHash) */\n transactionHash: string;\n /** The sender address (duplicate of receipt.from) */\n from: string;\n /** Timestamp when the transaction was created */\n createdAt: string;\n /** The contract address involved in the transaction */\n address: string;\n /** The name of the function called in the transaction */\n functionName: string;\n /** Whether the transaction is a contract deployment */\n isContract: boolean;\n}\n\ninterface GetTransactionResponse {\n getTransaction: Transaction;\n}\n\n/**\n * Options for waiting for a transaction receipt\n */\nexport interface WaitForTransactionReceiptOptions extends WebsocketClientOptions {\n /** Optional timeout in milliseconds before the operation fails */\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 = getWebsocketClient(options);\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","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 * Type representing the different types of wallet verification methods\n */\nexport type WalletVerificationType = \"PINCODE\" | \"OTP\" | \"SECRET_CODES\";\n\n/**\n * Custom error class for challenge-related errors\n */\nexport class WalletVerificationChallengeError 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 id: string;\n name: string;\n verificationId: string;\n verificationType: WalletVerificationType;\n challenge?: {\n salt: string;\n secret: string;\n };\n}\n\n/**\n * Response type for the CreateWalletVerificationChallenge mutation\n */\ninterface CreateWalletVerificationChallengeResponse {\n createWalletVerificationChallenge: 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 */\nexport interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSchema> {\n /** The portal client instance */\n portalClient: GraphQLClient;\n /** The GraphQL query builder */\n portalGraphql: initGraphQLTada<Setup>;\n /** The ID of the verification challenge */\n verificationId: string;\n /** The wallet address to verify */\n userWalletAddress: Address;\n /** The verification code provided by the user */\n code: string | number;\n /** The type of verification being performed */\n verificationType: WalletVerificationType;\n /** Request id which can be added for tracing purposes */\n requestId?: string;\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 {WalletVerificationChallengeError} 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 requestId,\n}: HandleWalletVerificationChallengeOptions<Setup>): Promise<{\n challengeResponse: string;\n challengeId: string;\n}> {\n try {\n const requestHeaders = new Headers();\n if (requestId) {\n requestHeaders.append(\"x-request-id\", requestId);\n }\n const verificationChallenge = await portalClient.request<CreateWalletVerificationChallengeResponse>(\n portalGraphql(`\n mutation CreateWalletVerificationChallenge($userWalletAddress: String!, $verificationId: String!) {\n createWalletVerificationChallenge(\n userWalletAddress: $userWalletAddress\n verificationId: $verificationId\n ) {\n id\n name\n verificationId\n verificationType\n challenge {\n salt\n secret\n }\n }\n }\n `),\n {\n userWalletAddress,\n verificationId,\n },\n requestHeaders,\n );\n\n if (!verificationChallenge.createWalletVerificationChallenge) {\n throw new WalletVerificationChallengeError(\"No verification challenge received\", \"NO_CHALLENGES\");\n }\n\n if (verificationType === \"OTP\") {\n return {\n challengeResponse: code.toString(),\n challengeId: verificationChallenge.createWalletVerificationChallenge.id,\n };\n }\n\n if (verificationType === \"SECRET_CODES\") {\n // Add - separator to the code\n const formattedCode = code.toString().replace(/(.{5})(?=.)/, \"$1-\");\n return {\n challengeResponse: formattedCode,\n challengeId: verificationChallenge.createWalletVerificationChallenge.id,\n };\n }\n\n const { secret, salt } = verificationChallenge.createWalletVerificationChallenge.challenge ?? {};\n\n if (!secret || !salt) {\n throw new WalletVerificationChallengeError(\"Invalid challenge format\", \"INVALID_CHALLENGE\");\n }\n\n const challengeResponse = generateResponse(code.toString(), salt, secret);\n return {\n challengeResponse,\n challengeId: verificationChallenge.createWalletVerificationChallenge.id,\n };\n } catch (error) {\n if (error instanceof WalletVerificationChallengeError) {\n throw error;\n }\n throw new WalletVerificationChallengeError(\n \"Failed to process wallet verification challenge\",\n \"CHALLENGE_PROCESSING_ERROR\",\n );\n }\n}\n","import { appendHeaders } from \"@settlemint/sdk-utils/http\";\nimport { 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.optional(),\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: appendHeaders(clientOptions?.headers, { \"x-auth-token\": validatedOptions.accessToken }),\n }),\n graphql,\n };\n}\n\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport { readFragment } from \"gql.tada\";\nexport {\n type Transaction,\n type TransactionEvent,\n type TransactionReceipt,\n type WaitForTransactionReceiptOptions,\n waitForTransactionReceipt,\n} from \"./utils/wait-for-transaction-receipt.js\";\nexport {\n type HandleWalletVerificationChallengeOptions,\n handleWalletVerificationChallenge,\n WalletVerificationChallengeError,\n type WalletVerificationType,\n} from \"./utils/wallet-verification-challenge.js\";\nexport { getWebsocketClient, type WebsocketClientOptions } from \"./utils/websocket-client.js\";\n"],"mappings":"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"}
package/dist/portal.cjs CHANGED
@@ -136,7 +136,7 @@ async function getTransactionFromSubscription(subscription) {
136
136
  /**
137
137
  * Custom error class for challenge-related errors
138
138
  */
139
- var ChallengeError = class extends Error {
139
+ var WalletVerificationChallengeError = class extends Error {
140
140
  code;
141
141
  constructor(message, code) {
142
142
  super(message);
@@ -169,7 +169,7 @@ function generateResponse(pincode, salt, challenge) {
169
169
  *
170
170
  * @param options - The options for handling the wallet verification challenge
171
171
  * @returns Promise resolving to an object containing the challenge response and optionally the verification ID
172
- * @throws {ChallengeError} If the challenge cannot be created or is invalid
172
+ * @throws {WalletVerificationChallengeError} If the challenge cannot be created or is invalid
173
173
  * @example
174
174
  * import { createPortalClient } from "@settlemint/sdk-portal";
175
175
  * import { handleWalletVerificationChallenge } from "@settlemint/sdk-portal";
@@ -185,55 +185,65 @@ function generateResponse(pincode, salt, challenge) {
185
185
  * verificationId: "verification-123",
186
186
  * userWalletAddress: "0x123...",
187
187
  * code: "123456",
188
- * verificationType: "otp"
188
+ * verificationType: "OTP"
189
189
  * });
190
190
  */
191
- async function handleWalletVerificationChallenge({ portalClient, portalGraphql, verificationId, userWalletAddress, code, verificationType }) {
191
+ async function handleWalletVerificationChallenge({ portalClient, portalGraphql, verificationId, userWalletAddress, code, verificationType, requestId }) {
192
192
  try {
193
- if (verificationType === "otp") {
194
- return {
195
- challengeResponse: code.toString(),
196
- verificationId
197
- };
198
- }
199
- if (verificationType === "secret-code") {
200
- const formattedCode = code.toString().replace(/(.{5})(?=.)/, "$1-");
201
- return {
202
- challengeResponse: formattedCode,
203
- verificationId
204
- };
193
+ const requestHeaders = new Headers();
194
+ if (requestId) {
195
+ requestHeaders.append("x-request-id", requestId);
205
196
  }
206
- const verificationChallenges = await portalClient.request(portalGraphql(`
207
- mutation CreateWalletVerificationChallenges($userWalletAddress: String!, $verificationId: String!) {
208
- createWalletVerificationChallenges(userWalletAddress: $userWalletAddress, verificationId: $verificationId) {
209
- challenge
197
+ const verificationChallenge = await portalClient.request(portalGraphql(`
198
+ mutation CreateWalletVerificationChallenge($userWalletAddress: String!, $verificationId: String!) {
199
+ createWalletVerificationChallenge(
200
+ userWalletAddress: $userWalletAddress
201
+ verificationId: $verificationId
202
+ ) {
210
203
  id
211
204
  name
205
+ verificationId
212
206
  verificationType
207
+ challenge {
208
+ salt
209
+ secret
210
+ }
213
211
  }
214
212
  }
215
213
  `), {
216
214
  userWalletAddress,
217
215
  verificationId
218
- });
219
- if (!verificationChallenges.createWalletVerificationChallenges?.length) {
220
- throw new ChallengeError("No verification challenges received", "NO_CHALLENGES");
216
+ }, requestHeaders);
217
+ if (!verificationChallenge.createWalletVerificationChallenge) {
218
+ throw new WalletVerificationChallengeError("No verification challenge received", "NO_CHALLENGES");
221
219
  }
222
- const walletVerificationChallenge = verificationChallenges.createWalletVerificationChallenges.find((challenge) => challenge.id === verificationId);
223
- if (!walletVerificationChallenge?.challenge?.secret || !walletVerificationChallenge?.challenge?.salt) {
224
- throw new ChallengeError("Invalid challenge format", "INVALID_CHALLENGE");
220
+ if (verificationType === "OTP") {
221
+ return {
222
+ challengeResponse: code.toString(),
223
+ challengeId: verificationChallenge.createWalletVerificationChallenge.id
224
+ };
225
+ }
226
+ if (verificationType === "SECRET_CODES") {
227
+ const formattedCode = code.toString().replace(/(.{5})(?=.)/, "$1-");
228
+ return {
229
+ challengeResponse: formattedCode,
230
+ challengeId: verificationChallenge.createWalletVerificationChallenge.id
231
+ };
232
+ }
233
+ const { secret, salt } = verificationChallenge.createWalletVerificationChallenge.challenge ?? {};
234
+ if (!secret || !salt) {
235
+ throw new WalletVerificationChallengeError("Invalid challenge format", "INVALID_CHALLENGE");
225
236
  }
226
- const { secret, salt } = walletVerificationChallenge.challenge;
227
237
  const challengeResponse = generateResponse(code.toString(), salt, secret);
228
238
  return {
229
239
  challengeResponse,
230
- verificationId
240
+ challengeId: verificationChallenge.createWalletVerificationChallenge.id
231
241
  };
232
242
  } catch (error) {
233
- if (error instanceof ChallengeError) {
243
+ if (error instanceof WalletVerificationChallengeError) {
234
244
  throw error;
235
245
  }
236
- throw new ChallengeError("Failed to process wallet verification challenge", "CHALLENGE_PROCESSING_ERROR");
246
+ throw new WalletVerificationChallengeError("Failed to process wallet verification challenge", "CHALLENGE_PROCESSING_ERROR");
237
247
  }
238
248
  }
239
249
 
@@ -315,6 +325,7 @@ function createPortalClient(options, clientOptions) {
315
325
 
316
326
  //#endregion
317
327
  exports.ClientOptionsSchema = ClientOptionsSchema;
328
+ exports.WalletVerificationChallengeError = WalletVerificationChallengeError;
318
329
  exports.createPortalClient = createPortalClient;
319
330
  exports.getWebsocketClient = getWebsocketClient;
320
331
  exports.handleWalletVerificationChallenge = handleWalletVerificationChallenge;
@@ -1 +1 @@
1
- {"version":3,"file":"portal.cjs","names":["url: URL","transactionHash: string","options: WaitForTransactionReceiptOptions","timeout: number","subscription: AsyncIterableIterator<FormattedExecutionResult<GetTransactionResponse, unknown>>","message: string","code: string","pincode: string","salt: string","challenge: string","z","UrlOrPathSchema","ApplicationAccessTokenSchema","options: ClientOptions","clientOptions?: RequestConfig","GraphQLClient"],"sources":["../src/utils/websocket-client.ts","../src/utils/wait-for-transaction-receipt.ts","../src/utils/wallet-verification-challenge.ts","../src/portal.ts"],"sourcesContent":["import { createClient } from \"graphql-ws\";\n\n/**\n * Options for the GraphQL WebSocket client\n */\nexport interface WebsocketClientOptions {\n /**\n * The GraphQL endpoint URL for the Portal API\n */\n portalGraphqlEndpoint: string;\n /**\n * The access token for authentication with the Portal API\n */\n accessToken?: string;\n}\n\n/**\n * Creates a GraphQL WebSocket client for the Portal API\n *\n * @param {WebsocketClientOptions} options - The options for the client\n * @returns {Client} The GraphQL WebSocket client\n * @example\n * import { getWebsocketClient } from \"@settlemint/sdk-portal\";\n *\n * const client = getWebsocketClient({\n * portalGraphqlEndpoint: \"https://portal.settlemint.com/graphql\",\n * accessToken: \"your-access-token\",\n * });\n */\nexport function getWebsocketClient({ portalGraphqlEndpoint, accessToken }: WebsocketClientOptions) {\n if (!portalGraphqlEndpoint) {\n throw new Error(\"portalGraphqlEndpoint is required\");\n }\n const graphqlEndpoint = setWsProtocol(new URL(portalGraphqlEndpoint));\n return createClient({\n url: accessToken\n ? `${graphqlEndpoint.protocol}//${graphqlEndpoint.host}/${accessToken}${graphqlEndpoint.pathname}${graphqlEndpoint.search}`\n : graphqlEndpoint.toString(),\n });\n}\n\nfunction setWsProtocol(url: URL) {\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n return url;\n }\n if (url.protocol === \"http:\") {\n url.protocol = \"ws:\";\n } else {\n url.protocol = \"wss:\";\n }\n return url;\n}\n","import type { FormattedExecutionResult } from \"graphql-ws\";\nimport type { Address, Hex, TransactionReceipt as TransactionReceiptViem } from \"viem\";\nimport { type WebsocketClientOptions, getWebsocketClient } from \"./websocket-client.js\";\n\n/**\n * Represents an event emitted during a transaction execution\n */\nexport interface TransactionEvent {\n /** The name of the event that was emitted */\n eventName: string;\n /** The arguments emitted by the event */\n args: Record<string, unknown>;\n /** Indexed event parameters used for filtering and searching */\n topics: Hex[];\n}\n\n/**\n * Represents the structure of a blockchain transaction receipt\n */\nexport interface TransactionReceipt extends TransactionReceiptViem<string, number, \"Success\" | \"Reverted\"> {\n /** The raw reason for transaction reversion, if applicable */\n revertReason: string;\n /** Human-readable version of the revert reason */\n revertReasonDecoded: string;\n /** Array of events emitted during the transaction */\n events: TransactionEvent[];\n /** The address of the contract deployed in the transaction */\n contractAddress: Address;\n}\n\n/**\n * Represents the structure of a blockchain transaction with its receipt\n */\nexport interface Transaction {\n receipt: TransactionReceipt;\n /** The hash of the transaction (duplicate of receipt.transactionHash) */\n transactionHash: string;\n /** The sender address (duplicate of receipt.from) */\n from: string;\n /** Timestamp when the transaction was created */\n createdAt: string;\n /** The contract address involved in the transaction */\n address: string;\n /** The name of the function called in the transaction */\n functionName: string;\n /** Whether the transaction is a contract deployment */\n isContract: boolean;\n}\n\ninterface GetTransactionResponse {\n getTransaction: Transaction;\n}\n\n/**\n * Options for waiting for a transaction receipt\n */\nexport interface WaitForTransactionReceiptOptions extends WebsocketClientOptions {\n /** Optional timeout in milliseconds before the operation fails */\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 = getWebsocketClient(options);\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","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 */\nexport interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSchema> {\n /** The portal client instance */\n portalClient: GraphQLClient;\n /** The GraphQL query builder */\n portalGraphql: initGraphQLTada<Setup>;\n /** The ID of the verification challenge */\n verificationId: string;\n /** The wallet address to verify */\n userWalletAddress: Address;\n /** The verification code provided by the user */\n code: string | number;\n /** The type of verification being performed */\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 { appendHeaders } from \"@settlemint/sdk-utils/http\";\nimport { 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.optional(),\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: appendHeaders(clientOptions?.headers, { \"x-auth-token\": validatedOptions.accessToken }),\n }),\n graphql,\n };\n}\n\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport { readFragment } from \"gql.tada\";\nexport {\n type Transaction,\n type TransactionEvent,\n type TransactionReceipt,\n type WaitForTransactionReceiptOptions,\n waitForTransactionReceipt,\n} from \"./utils/wait-for-transaction-receipt.js\";\nexport {\n type HandleWalletVerificationChallengeOptions,\n handleWalletVerificationChallenge,\n} from \"./utils/wallet-verification-challenge.js\";\nexport { getWebsocketClient, type WebsocketClientOptions } from \"./utils/websocket-client.js\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"portal.cjs","names":["url: URL","transactionHash: string","options: WaitForTransactionReceiptOptions","timeout: number","subscription: AsyncIterableIterator<FormattedExecutionResult<GetTransactionResponse, unknown>>","message: string","code: string","pincode: string","salt: string","challenge: string","z","UrlOrPathSchema","ApplicationAccessTokenSchema","options: ClientOptions","clientOptions?: RequestConfig","GraphQLClient"],"sources":["../src/utils/websocket-client.ts","../src/utils/wait-for-transaction-receipt.ts","../src/utils/wallet-verification-challenge.ts","../src/portal.ts"],"sourcesContent":["import { createClient } from \"graphql-ws\";\n\n/**\n * Options for the GraphQL WebSocket client\n */\nexport interface WebsocketClientOptions {\n /**\n * The GraphQL endpoint URL for the Portal API\n */\n portalGraphqlEndpoint: string;\n /**\n * The access token for authentication with the Portal API\n */\n accessToken?: string;\n}\n\n/**\n * Creates a GraphQL WebSocket client for the Portal API\n *\n * @param {WebsocketClientOptions} options - The options for the client\n * @returns {Client} The GraphQL WebSocket client\n * @example\n * import { getWebsocketClient } from \"@settlemint/sdk-portal\";\n *\n * const client = getWebsocketClient({\n * portalGraphqlEndpoint: \"https://portal.settlemint.com/graphql\",\n * accessToken: \"your-access-token\",\n * });\n */\nexport function getWebsocketClient({ portalGraphqlEndpoint, accessToken }: WebsocketClientOptions) {\n if (!portalGraphqlEndpoint) {\n throw new Error(\"portalGraphqlEndpoint is required\");\n }\n const graphqlEndpoint = setWsProtocol(new URL(portalGraphqlEndpoint));\n return createClient({\n url: accessToken\n ? `${graphqlEndpoint.protocol}//${graphqlEndpoint.host}/${accessToken}${graphqlEndpoint.pathname}${graphqlEndpoint.search}`\n : graphqlEndpoint.toString(),\n });\n}\n\nfunction setWsProtocol(url: URL) {\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n return url;\n }\n if (url.protocol === \"http:\") {\n url.protocol = \"ws:\";\n } else {\n url.protocol = \"wss:\";\n }\n return url;\n}\n","import type { FormattedExecutionResult } from \"graphql-ws\";\nimport type { Address, Hex, TransactionReceipt as TransactionReceiptViem } from \"viem\";\nimport { type WebsocketClientOptions, getWebsocketClient } from \"./websocket-client.js\";\n\n/**\n * Represents an event emitted during a transaction execution\n */\nexport interface TransactionEvent {\n /** The name of the event that was emitted */\n eventName: string;\n /** The arguments emitted by the event */\n args: Record<string, unknown>;\n /** Indexed event parameters used for filtering and searching */\n topics: Hex[];\n}\n\n/**\n * Represents the structure of a blockchain transaction receipt\n */\nexport interface TransactionReceipt extends TransactionReceiptViem<string, number, \"Success\" | \"Reverted\"> {\n /** The raw reason for transaction reversion, if applicable */\n revertReason: string;\n /** Human-readable version of the revert reason */\n revertReasonDecoded: string;\n /** Array of events emitted during the transaction */\n events: TransactionEvent[];\n /** The address of the contract deployed in the transaction */\n contractAddress: Address;\n}\n\n/**\n * Represents the structure of a blockchain transaction with its receipt\n */\nexport interface Transaction {\n receipt: TransactionReceipt;\n /** The hash of the transaction (duplicate of receipt.transactionHash) */\n transactionHash: string;\n /** The sender address (duplicate of receipt.from) */\n from: string;\n /** Timestamp when the transaction was created */\n createdAt: string;\n /** The contract address involved in the transaction */\n address: string;\n /** The name of the function called in the transaction */\n functionName: string;\n /** Whether the transaction is a contract deployment */\n isContract: boolean;\n}\n\ninterface GetTransactionResponse {\n getTransaction: Transaction;\n}\n\n/**\n * Options for waiting for a transaction receipt\n */\nexport interface WaitForTransactionReceiptOptions extends WebsocketClientOptions {\n /** Optional timeout in milliseconds before the operation fails */\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 = getWebsocketClient(options);\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","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 * Type representing the different types of wallet verification methods\n */\nexport type WalletVerificationType = \"PINCODE\" | \"OTP\" | \"SECRET_CODES\";\n\n/**\n * Custom error class for challenge-related errors\n */\nexport class WalletVerificationChallengeError 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 id: string;\n name: string;\n verificationId: string;\n verificationType: WalletVerificationType;\n challenge?: {\n salt: string;\n secret: string;\n };\n}\n\n/**\n * Response type for the CreateWalletVerificationChallenge mutation\n */\ninterface CreateWalletVerificationChallengeResponse {\n createWalletVerificationChallenge: 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 */\nexport interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSchema> {\n /** The portal client instance */\n portalClient: GraphQLClient;\n /** The GraphQL query builder */\n portalGraphql: initGraphQLTada<Setup>;\n /** The ID of the verification challenge */\n verificationId: string;\n /** The wallet address to verify */\n userWalletAddress: Address;\n /** The verification code provided by the user */\n code: string | number;\n /** The type of verification being performed */\n verificationType: WalletVerificationType;\n /** Request id which can be added for tracing purposes */\n requestId?: string;\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 {WalletVerificationChallengeError} 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 requestId,\n}: HandleWalletVerificationChallengeOptions<Setup>): Promise<{\n challengeResponse: string;\n challengeId: string;\n}> {\n try {\n const requestHeaders = new Headers();\n if (requestId) {\n requestHeaders.append(\"x-request-id\", requestId);\n }\n const verificationChallenge = await portalClient.request<CreateWalletVerificationChallengeResponse>(\n portalGraphql(`\n mutation CreateWalletVerificationChallenge($userWalletAddress: String!, $verificationId: String!) {\n createWalletVerificationChallenge(\n userWalletAddress: $userWalletAddress\n verificationId: $verificationId\n ) {\n id\n name\n verificationId\n verificationType\n challenge {\n salt\n secret\n }\n }\n }\n `),\n {\n userWalletAddress,\n verificationId,\n },\n requestHeaders,\n );\n\n if (!verificationChallenge.createWalletVerificationChallenge) {\n throw new WalletVerificationChallengeError(\"No verification challenge received\", \"NO_CHALLENGES\");\n }\n\n if (verificationType === \"OTP\") {\n return {\n challengeResponse: code.toString(),\n challengeId: verificationChallenge.createWalletVerificationChallenge.id,\n };\n }\n\n if (verificationType === \"SECRET_CODES\") {\n // Add - separator to the code\n const formattedCode = code.toString().replace(/(.{5})(?=.)/, \"$1-\");\n return {\n challengeResponse: formattedCode,\n challengeId: verificationChallenge.createWalletVerificationChallenge.id,\n };\n }\n\n const { secret, salt } = verificationChallenge.createWalletVerificationChallenge.challenge ?? {};\n\n if (!secret || !salt) {\n throw new WalletVerificationChallengeError(\"Invalid challenge format\", \"INVALID_CHALLENGE\");\n }\n\n const challengeResponse = generateResponse(code.toString(), salt, secret);\n return {\n challengeResponse,\n challengeId: verificationChallenge.createWalletVerificationChallenge.id,\n };\n } catch (error) {\n if (error instanceof WalletVerificationChallengeError) {\n throw error;\n }\n throw new WalletVerificationChallengeError(\n \"Failed to process wallet verification challenge\",\n \"CHALLENGE_PROCESSING_ERROR\",\n );\n }\n}\n","import { appendHeaders } from \"@settlemint/sdk-utils/http\";\nimport { 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.optional(),\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: appendHeaders(clientOptions?.headers, { \"x-auth-token\": validatedOptions.accessToken }),\n }),\n graphql,\n };\n}\n\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport { readFragment } from \"gql.tada\";\nexport {\n type Transaction,\n type TransactionEvent,\n type TransactionReceipt,\n type WaitForTransactionReceiptOptions,\n waitForTransactionReceipt,\n} from \"./utils/wait-for-transaction-receipt.js\";\nexport {\n type HandleWalletVerificationChallengeOptions,\n handleWalletVerificationChallenge,\n WalletVerificationChallengeError,\n type WalletVerificationType,\n} from \"./utils/wallet-verification-challenge.js\";\nexport { getWebsocketClient, type WebsocketClientOptions } from \"./utils/websocket-client.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAgB,mBAAmB,EAAE,uBAAuB,aAAqC,EAAE;AACjG,KAAI,CAAC,uBAAuB;AAC1B,QAAM,IAAI,MAAM;CACjB;CACD,MAAM,kBAAkB,cAAc,IAAI,IAAI,uBAAuB;AACrE,qCAAoB,EAClB,KAAK,cACD,GAAG,gBAAgB,SAAS,EAAE,EAAE,gBAAgB,KAAK,CAAC,EAAE,cAAc,gBAAgB,WAAW,gBAAgB,QAAQ,GACzH,gBAAgB,UAAU,CAC/B,EAAC;AACH;AAED,SAAS,cAAcA,KAAU;AAC/B,KAAI,IAAI,aAAa,SAAS,IAAI,aAAa,QAAQ;AACrD,SAAO;CACR;AACD,KAAI,IAAI,aAAa,SAAS;EAC5B,IAAI,WAAW;CAChB,OAAM;EACL,IAAI,WAAW;CAChB;AACD,QAAO;AACR;;;;;;;;;;;;;;;;;;;;;;AC4BD,eAAsB,0BAA0BC,iBAAyBC,SAA2C;CAClH,MAAM,WAAW,mBAAmB,QAAQ;CAC5C,MAAM,eAAe,SAAS,QAAgC;EAC5D,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;OAqBL,CAAC;EACJ,WAAW,EAAE,gBAAiB;CAC/B,EAAC;CACF,MAAM,WAAW,CAAC,+BAA+B,aAAa,AAAC;AAC/D,KAAI,QAAQ,SAAS;EACnB,SAAS,KAAK,qBAAqB,QAAQ,QAAQ,CAAC;CACrD;AAED,QAAO,QAAQ,KAAK,SAAS;AAC9B;AAED,SAAS,qBAAqBC,SAAiC;AAC7D,QAAO,IAAI,QAAQ,CAAC,GAAG,WAAW;EAChC,WAAW,MAAM,OAAO,IAAI,MAAM,iCAAiC,EAAE,QAAQ;CAC9E;AACF;AAED,eAAe,+BACbC,cACsB;AACtB,YAAW,MAAM,UAAU,cAAc;AACvC,MAAI,QAAQ,MAAM,gBAAgB,SAAS;AACzC,UAAO,OAAO,KAAK;EACpB;CACF;AACD,OAAM,IAAI,MAAM;AACjB;;;;;;;ACpHD,IAAa,mCAAb,cAAsD,MAAM;CAC1D,AAAS;CAET,YAAYC,SAAiBC,MAAc;EACzC,MAAM,QAAQ;EACd,KAAK,OAAO;EACZ,KAAK,OAAO;CACb;AACF;;;;;;;AA6BD,SAAS,YAAYC,SAAiBC,MAAsB;AAC1D,oCAAkB,SAAS,CAAC,OAAO,GAAG,OAAO,SAAS,CAAC,CAAC,OAAO,MAAM;AACtE;;;;;;;;AASD,SAAS,iBAAiBD,SAAiBC,MAAcC,WAA2B;CAClF,MAAM,gBAAgB,YAAY,SAAS,KAAK;AAChD,oCAAkB,SAAS,CAAC,OAAO,GAAG,cAAc,CAAC,EAAE,WAAW,CAAC,CAAC,OAAO,MAAM;AAClF;;;;;;;;;;;;;;;;;;;;;;;;;AA8CD,eAAsB,kCAA2E,EAC/F,cACA,eACA,gBACA,mBACA,MACA,kBACA,WACgD,EAG/C;AACD,KAAI;EACF,MAAM,iBAAiB,IAAI;AAC3B,MAAI,WAAW;GACb,eAAe,OAAO,gBAAgB,UAAU;EACjD;EACD,MAAM,wBAAwB,MAAM,aAAa,QAC/C,cAAc,CAAC;;;;;;;;;;;;;;;;MAgBf,CAAC,CAAC,EACF;GACE;GACA;EACD,GACD,eACD;AAED,MAAI,CAAC,sBAAsB,mCAAmC;AAC5D,SAAM,IAAI,iCAAiC,sCAAsC;EAClF;AAED,MAAI,qBAAqB,OAAO;AAC9B,UAAO;IACL,mBAAmB,KAAK,UAAU;IAClC,aAAa,sBAAsB,kCAAkC;GACtE;EACF;AAED,MAAI,qBAAqB,gBAAgB;GAEvC,MAAM,gBAAgB,KAAK,UAAU,CAAC,QAAQ,eAAe,MAAM;AACnE,UAAO;IACL,mBAAmB;IACnB,aAAa,sBAAsB,kCAAkC;GACtE;EACF;EAED,MAAM,EAAE,QAAQ,MAAM,GAAG,sBAAsB,kCAAkC,aAAa,CAAE;AAEhG,MAAI,CAAC,UAAU,CAAC,MAAM;AACpB,SAAM,IAAI,iCAAiC,4BAA4B;EACxE;EAED,MAAM,oBAAoB,iBAAiB,KAAK,UAAU,EAAE,MAAM,OAAO;AACzE,SAAO;GACL;GACA,aAAa,sBAAsB,kCAAkC;EACtE;CACF,SAAQ,OAAO;AACd,MAAI,iBAAiB,kCAAkC;AACrD,SAAM;EACP;AACD,QAAM,IAAI,iCACR,mDACA;CAEH;AACF;;;;;;;ACjLD,MAAa,sBAAsBC,MAAE,OAAO;CAC1C,UAAUC;CACV,aAAaC,+DAA6B,UAAU;CACpD,OAAOF,MAAE,KAAK;EAAC;EAAW;EAAe;EAAY;EAAY;EAAkB;CAAS,EAAC,CAAC,UAAU;AACzG,EAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDF,SAAgB,mBACdG,SACAC,eAIA;mDACc;CACd,MAAM,mEAA4B,qBAAqB,QAAQ;CAC/D,MAAM,yCAAkC;CACxC,MAAM,UAAU,IAAI,IAAI,iBAAiB,UAAU,UAAU;AAE7D,QAAO;EACL,QAAQ,IAAIC,8BAAc,SAAS;GACjC,GAAG;GACH,wDAAuB,eAAe,SAAS,EAAE,gBAAgB,iBAAiB,YAAa,EAAC;EACjG;EACD;CACD;AACF"}
package/dist/portal.d.cts CHANGED
@@ -108,10 +108,14 @@ interface WaitForTransactionReceiptOptions extends WebsocketClientOptions {
108
108
  declare function waitForTransactionReceipt(transactionHash: string, options: WaitForTransactionReceiptOptions): Promise<Transaction>;
109
109
  //#endregion
110
110
  //#region src/utils/wallet-verification-challenge.d.ts
111
+ /**
112
+ * Type representing the different types of wallet verification methods
113
+ */
114
+ type WalletVerificationType = "PINCODE" | "OTP" | "SECRET_CODES";
111
115
  /**
112
116
  * Custom error class for challenge-related errors
113
117
  */
114
- declare class ChallengeError extends Error {
118
+ declare class WalletVerificationChallengeError extends Error {
115
119
  readonly code: string;
116
120
  constructor(message: string, code: string);
117
121
  }
@@ -130,14 +134,16 @@ interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSc
130
134
  /** The verification code provided by the user */
131
135
  code: string | number;
132
136
  /** The type of verification being performed */
133
- verificationType: "otp" | "secret-code" | "pincode";
137
+ verificationType: WalletVerificationType;
138
+ /** Request id which can be added for tracing purposes */
139
+ requestId?: string;
134
140
  }
135
141
  /**
136
142
  * Handles a wallet verification challenge by generating an appropriate response
137
143
  *
138
144
  * @param options - The options for handling the wallet verification challenge
139
145
  * @returns Promise resolving to an object containing the challenge response and optionally the verification ID
140
- * @throws {ChallengeError} If the challenge cannot be created or is invalid
146
+ * @throws {WalletVerificationChallengeError} If the challenge cannot be created or is invalid
141
147
  * @example
142
148
  * import { createPortalClient } from "@settlemint/sdk-portal";
143
149
  * import { handleWalletVerificationChallenge } from "@settlemint/sdk-portal";
@@ -153,7 +159,7 @@ interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSc
153
159
  * verificationId: "verification-123",
154
160
  * userWalletAddress: "0x123...",
155
161
  * code: "123456",
156
- * verificationType: "otp"
162
+ * verificationType: "OTP"
157
163
  * });
158
164
  */
159
165
  declare function handleWalletVerificationChallenge<const Setup extends AbstractSetupSchema>({
@@ -162,10 +168,11 @@ declare function handleWalletVerificationChallenge<const Setup extends AbstractS
162
168
  verificationId,
163
169
  userWalletAddress,
164
170
  code,
165
- verificationType
171
+ verificationType,
172
+ requestId
166
173
  }: HandleWalletVerificationChallengeOptions<Setup>): Promise<{
167
174
  challengeResponse: string;
168
- verificationId?: string;
175
+ challengeId: string;
169
176
  }>;
170
177
  //#endregion
171
178
  //#region src/portal.d.ts
@@ -242,5 +249,5 @@ declare function createPortalClient<const Setup extends AbstractSetupSchema>(opt
242
249
  graphql: initGraphQLTada<Setup>;
243
250
  };
244
251
  //#endregion
245
- export { ClientOptions, ClientOptionsSchema, type FragmentOf, type HandleWalletVerificationChallengeOptions, RequestConfig, type ResultOf, type Transaction, type TransactionEvent, type TransactionReceipt, type VariablesOf, type WaitForTransactionReceiptOptions, type WebsocketClientOptions, createPortalClient, getWebsocketClient, handleWalletVerificationChallenge, readFragment, waitForTransactionReceipt };
252
+ export { ClientOptions, ClientOptionsSchema, type FragmentOf, type HandleWalletVerificationChallengeOptions, RequestConfig, type ResultOf, type Transaction, type TransactionEvent, type TransactionReceipt, type VariablesOf, type WaitForTransactionReceiptOptions, WalletVerificationChallengeError, type WalletVerificationType, type WebsocketClientOptions, createPortalClient, getWebsocketClient, handleWalletVerificationChallenge, readFragment, waitForTransactionReceipt };
246
253
  //# sourceMappingURL=portal.d.cts.map
package/dist/portal.d.ts CHANGED
@@ -108,10 +108,14 @@ interface WaitForTransactionReceiptOptions extends WebsocketClientOptions {
108
108
  declare function waitForTransactionReceipt(transactionHash: string, options: WaitForTransactionReceiptOptions): Promise<Transaction>;
109
109
  //#endregion
110
110
  //#region src/utils/wallet-verification-challenge.d.ts
111
+ /**
112
+ * Type representing the different types of wallet verification methods
113
+ */
114
+ type WalletVerificationType = "PINCODE" | "OTP" | "SECRET_CODES";
111
115
  /**
112
116
  * Custom error class for challenge-related errors
113
117
  */
114
- declare class ChallengeError extends Error {
118
+ declare class WalletVerificationChallengeError extends Error {
115
119
  readonly code: string;
116
120
  constructor(message: string, code: string);
117
121
  }
@@ -130,14 +134,16 @@ interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSc
130
134
  /** The verification code provided by the user */
131
135
  code: string | number;
132
136
  /** The type of verification being performed */
133
- verificationType: "otp" | "secret-code" | "pincode";
137
+ verificationType: WalletVerificationType;
138
+ /** Request id which can be added for tracing purposes */
139
+ requestId?: string;
134
140
  }
135
141
  /**
136
142
  * Handles a wallet verification challenge by generating an appropriate response
137
143
  *
138
144
  * @param options - The options for handling the wallet verification challenge
139
145
  * @returns Promise resolving to an object containing the challenge response and optionally the verification ID
140
- * @throws {ChallengeError} If the challenge cannot be created or is invalid
146
+ * @throws {WalletVerificationChallengeError} If the challenge cannot be created or is invalid
141
147
  * @example
142
148
  * import { createPortalClient } from "@settlemint/sdk-portal";
143
149
  * import { handleWalletVerificationChallenge } from "@settlemint/sdk-portal";
@@ -153,7 +159,7 @@ interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSc
153
159
  * verificationId: "verification-123",
154
160
  * userWalletAddress: "0x123...",
155
161
  * code: "123456",
156
- * verificationType: "otp"
162
+ * verificationType: "OTP"
157
163
  * });
158
164
  */
159
165
  declare function handleWalletVerificationChallenge<const Setup extends AbstractSetupSchema>({
@@ -162,10 +168,11 @@ declare function handleWalletVerificationChallenge<const Setup extends AbstractS
162
168
  verificationId,
163
169
  userWalletAddress,
164
170
  code,
165
- verificationType
171
+ verificationType,
172
+ requestId
166
173
  }: HandleWalletVerificationChallengeOptions<Setup>): Promise<{
167
174
  challengeResponse: string;
168
- verificationId?: string;
175
+ challengeId: string;
169
176
  }>;
170
177
  //#endregion
171
178
  //#region src/portal.d.ts
@@ -242,5 +249,5 @@ declare function createPortalClient<const Setup extends AbstractSetupSchema>(opt
242
249
  graphql: initGraphQLTada<Setup>;
243
250
  };
244
251
  //#endregion
245
- export { ClientOptions, ClientOptionsSchema, type FragmentOf, type HandleWalletVerificationChallengeOptions, RequestConfig, type ResultOf, type Transaction, type TransactionEvent, type TransactionReceipt, type VariablesOf, type WaitForTransactionReceiptOptions, type WebsocketClientOptions, createPortalClient, getWebsocketClient, handleWalletVerificationChallenge, readFragment, waitForTransactionReceipt };
252
+ export { ClientOptions, ClientOptionsSchema, type FragmentOf, type HandleWalletVerificationChallengeOptions, RequestConfig, type ResultOf, type Transaction, type TransactionEvent, type TransactionReceipt, type VariablesOf, type WaitForTransactionReceiptOptions, WalletVerificationChallengeError, type WalletVerificationType, type WebsocketClientOptions, createPortalClient, getWebsocketClient, handleWalletVerificationChallenge, readFragment, waitForTransactionReceipt };
246
253
  //# sourceMappingURL=portal.d.ts.map
package/dist/portal.js CHANGED
@@ -113,7 +113,7 @@ async function getTransactionFromSubscription(subscription) {
113
113
  /**
114
114
  * Custom error class for challenge-related errors
115
115
  */
116
- var ChallengeError = class extends Error {
116
+ var WalletVerificationChallengeError = class extends Error {
117
117
  code;
118
118
  constructor(message, code) {
119
119
  super(message);
@@ -146,7 +146,7 @@ function generateResponse(pincode, salt, challenge) {
146
146
  *
147
147
  * @param options - The options for handling the wallet verification challenge
148
148
  * @returns Promise resolving to an object containing the challenge response and optionally the verification ID
149
- * @throws {ChallengeError} If the challenge cannot be created or is invalid
149
+ * @throws {WalletVerificationChallengeError} If the challenge cannot be created or is invalid
150
150
  * @example
151
151
  * import { createPortalClient } from "@settlemint/sdk-portal";
152
152
  * import { handleWalletVerificationChallenge } from "@settlemint/sdk-portal";
@@ -162,55 +162,65 @@ function generateResponse(pincode, salt, challenge) {
162
162
  * verificationId: "verification-123",
163
163
  * userWalletAddress: "0x123...",
164
164
  * code: "123456",
165
- * verificationType: "otp"
165
+ * verificationType: "OTP"
166
166
  * });
167
167
  */
168
- async function handleWalletVerificationChallenge({ portalClient, portalGraphql, verificationId, userWalletAddress, code, verificationType }) {
168
+ async function handleWalletVerificationChallenge({ portalClient, portalGraphql, verificationId, userWalletAddress, code, verificationType, requestId }) {
169
169
  try {
170
- if (verificationType === "otp") {
171
- return {
172
- challengeResponse: code.toString(),
173
- verificationId
174
- };
170
+ const requestHeaders = new Headers();
171
+ if (requestId) {
172
+ requestHeaders.append("x-request-id", requestId);
175
173
  }
176
- if (verificationType === "secret-code") {
177
- const formattedCode = code.toString().replace(/(.{5})(?=.)/, "$1-");
178
- return {
179
- challengeResponse: formattedCode,
180
- verificationId
181
- };
182
- }
183
- const verificationChallenges = await portalClient.request(portalGraphql(`
184
- mutation CreateWalletVerificationChallenges($userWalletAddress: String!, $verificationId: String!) {
185
- createWalletVerificationChallenges(userWalletAddress: $userWalletAddress, verificationId: $verificationId) {
186
- challenge
174
+ const verificationChallenge = await portalClient.request(portalGraphql(`
175
+ mutation CreateWalletVerificationChallenge($userWalletAddress: String!, $verificationId: String!) {
176
+ createWalletVerificationChallenge(
177
+ userWalletAddress: $userWalletAddress
178
+ verificationId: $verificationId
179
+ ) {
187
180
  id
188
181
  name
182
+ verificationId
189
183
  verificationType
184
+ challenge {
185
+ salt
186
+ secret
187
+ }
190
188
  }
191
189
  }
192
190
  `), {
193
191
  userWalletAddress,
194
192
  verificationId
195
- });
196
- if (!verificationChallenges.createWalletVerificationChallenges?.length) {
197
- throw new ChallengeError("No verification challenges received", "NO_CHALLENGES");
193
+ }, requestHeaders);
194
+ if (!verificationChallenge.createWalletVerificationChallenge) {
195
+ throw new WalletVerificationChallengeError("No verification challenge received", "NO_CHALLENGES");
196
+ }
197
+ if (verificationType === "OTP") {
198
+ return {
199
+ challengeResponse: code.toString(),
200
+ challengeId: verificationChallenge.createWalletVerificationChallenge.id
201
+ };
198
202
  }
199
- const walletVerificationChallenge = verificationChallenges.createWalletVerificationChallenges.find((challenge) => challenge.id === verificationId);
200
- if (!walletVerificationChallenge?.challenge?.secret || !walletVerificationChallenge?.challenge?.salt) {
201
- throw new ChallengeError("Invalid challenge format", "INVALID_CHALLENGE");
203
+ if (verificationType === "SECRET_CODES") {
204
+ const formattedCode = code.toString().replace(/(.{5})(?=.)/, "$1-");
205
+ return {
206
+ challengeResponse: formattedCode,
207
+ challengeId: verificationChallenge.createWalletVerificationChallenge.id
208
+ };
209
+ }
210
+ const { secret, salt } = verificationChallenge.createWalletVerificationChallenge.challenge ?? {};
211
+ if (!secret || !salt) {
212
+ throw new WalletVerificationChallengeError("Invalid challenge format", "INVALID_CHALLENGE");
202
213
  }
203
- const { secret, salt } = walletVerificationChallenge.challenge;
204
214
  const challengeResponse = generateResponse(code.toString(), salt, secret);
205
215
  return {
206
216
  challengeResponse,
207
- verificationId
217
+ challengeId: verificationChallenge.createWalletVerificationChallenge.id
208
218
  };
209
219
  } catch (error) {
210
- if (error instanceof ChallengeError) {
220
+ if (error instanceof WalletVerificationChallengeError) {
211
221
  throw error;
212
222
  }
213
- throw new ChallengeError("Failed to process wallet verification challenge", "CHALLENGE_PROCESSING_ERROR");
223
+ throw new WalletVerificationChallengeError("Failed to process wallet verification challenge", "CHALLENGE_PROCESSING_ERROR");
214
224
  }
215
225
  }
216
226
 
@@ -291,5 +301,5 @@ function createPortalClient(options, clientOptions) {
291
301
  }
292
302
 
293
303
  //#endregion
294
- export { ClientOptionsSchema, createPortalClient, getWebsocketClient, handleWalletVerificationChallenge, readFragment, waitForTransactionReceipt };
304
+ export { ClientOptionsSchema, WalletVerificationChallengeError, createPortalClient, getWebsocketClient, handleWalletVerificationChallenge, readFragment, waitForTransactionReceipt };
295
305
  //# sourceMappingURL=portal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"portal.js","names":["url: URL","transactionHash: string","options: WaitForTransactionReceiptOptions","timeout: number","subscription: AsyncIterableIterator<FormattedExecutionResult<GetTransactionResponse, unknown>>","message: string","code: string","pincode: string","salt: string","challenge: string","options: ClientOptions","clientOptions?: RequestConfig"],"sources":["../src/utils/websocket-client.ts","../src/utils/wait-for-transaction-receipt.ts","../src/utils/wallet-verification-challenge.ts","../src/portal.ts"],"sourcesContent":["import { createClient } from \"graphql-ws\";\n\n/**\n * Options for the GraphQL WebSocket client\n */\nexport interface WebsocketClientOptions {\n /**\n * The GraphQL endpoint URL for the Portal API\n */\n portalGraphqlEndpoint: string;\n /**\n * The access token for authentication with the Portal API\n */\n accessToken?: string;\n}\n\n/**\n * Creates a GraphQL WebSocket client for the Portal API\n *\n * @param {WebsocketClientOptions} options - The options for the client\n * @returns {Client} The GraphQL WebSocket client\n * @example\n * import { getWebsocketClient } from \"@settlemint/sdk-portal\";\n *\n * const client = getWebsocketClient({\n * portalGraphqlEndpoint: \"https://portal.settlemint.com/graphql\",\n * accessToken: \"your-access-token\",\n * });\n */\nexport function getWebsocketClient({ portalGraphqlEndpoint, accessToken }: WebsocketClientOptions) {\n if (!portalGraphqlEndpoint) {\n throw new Error(\"portalGraphqlEndpoint is required\");\n }\n const graphqlEndpoint = setWsProtocol(new URL(portalGraphqlEndpoint));\n return createClient({\n url: accessToken\n ? `${graphqlEndpoint.protocol}//${graphqlEndpoint.host}/${accessToken}${graphqlEndpoint.pathname}${graphqlEndpoint.search}`\n : graphqlEndpoint.toString(),\n });\n}\n\nfunction setWsProtocol(url: URL) {\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n return url;\n }\n if (url.protocol === \"http:\") {\n url.protocol = \"ws:\";\n } else {\n url.protocol = \"wss:\";\n }\n return url;\n}\n","import type { FormattedExecutionResult } from \"graphql-ws\";\nimport type { Address, Hex, TransactionReceipt as TransactionReceiptViem } from \"viem\";\nimport { type WebsocketClientOptions, getWebsocketClient } from \"./websocket-client.js\";\n\n/**\n * Represents an event emitted during a transaction execution\n */\nexport interface TransactionEvent {\n /** The name of the event that was emitted */\n eventName: string;\n /** The arguments emitted by the event */\n args: Record<string, unknown>;\n /** Indexed event parameters used for filtering and searching */\n topics: Hex[];\n}\n\n/**\n * Represents the structure of a blockchain transaction receipt\n */\nexport interface TransactionReceipt extends TransactionReceiptViem<string, number, \"Success\" | \"Reverted\"> {\n /** The raw reason for transaction reversion, if applicable */\n revertReason: string;\n /** Human-readable version of the revert reason */\n revertReasonDecoded: string;\n /** Array of events emitted during the transaction */\n events: TransactionEvent[];\n /** The address of the contract deployed in the transaction */\n contractAddress: Address;\n}\n\n/**\n * Represents the structure of a blockchain transaction with its receipt\n */\nexport interface Transaction {\n receipt: TransactionReceipt;\n /** The hash of the transaction (duplicate of receipt.transactionHash) */\n transactionHash: string;\n /** The sender address (duplicate of receipt.from) */\n from: string;\n /** Timestamp when the transaction was created */\n createdAt: string;\n /** The contract address involved in the transaction */\n address: string;\n /** The name of the function called in the transaction */\n functionName: string;\n /** Whether the transaction is a contract deployment */\n isContract: boolean;\n}\n\ninterface GetTransactionResponse {\n getTransaction: Transaction;\n}\n\n/**\n * Options for waiting for a transaction receipt\n */\nexport interface WaitForTransactionReceiptOptions extends WebsocketClientOptions {\n /** Optional timeout in milliseconds before the operation fails */\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 = getWebsocketClient(options);\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","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 */\nexport interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSchema> {\n /** The portal client instance */\n portalClient: GraphQLClient;\n /** The GraphQL query builder */\n portalGraphql: initGraphQLTada<Setup>;\n /** The ID of the verification challenge */\n verificationId: string;\n /** The wallet address to verify */\n userWalletAddress: Address;\n /** The verification code provided by the user */\n code: string | number;\n /** The type of verification being performed */\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 { appendHeaders } from \"@settlemint/sdk-utils/http\";\nimport { 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.optional(),\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: appendHeaders(clientOptions?.headers, { \"x-auth-token\": validatedOptions.accessToken }),\n }),\n graphql,\n };\n}\n\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport { readFragment } from \"gql.tada\";\nexport {\n type Transaction,\n type TransactionEvent,\n type TransactionReceipt,\n type WaitForTransactionReceiptOptions,\n waitForTransactionReceipt,\n} from \"./utils/wait-for-transaction-receipt.js\";\nexport {\n type HandleWalletVerificationChallengeOptions,\n handleWalletVerificationChallenge,\n} from \"./utils/wallet-verification-challenge.js\";\nexport { getWebsocketClient, type WebsocketClientOptions } from \"./utils/websocket-client.js\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"portal.js","names":["url: URL","transactionHash: string","options: WaitForTransactionReceiptOptions","timeout: number","subscription: AsyncIterableIterator<FormattedExecutionResult<GetTransactionResponse, unknown>>","message: string","code: string","pincode: string","salt: string","challenge: string","options: ClientOptions","clientOptions?: RequestConfig"],"sources":["../src/utils/websocket-client.ts","../src/utils/wait-for-transaction-receipt.ts","../src/utils/wallet-verification-challenge.ts","../src/portal.ts"],"sourcesContent":["import { createClient } from \"graphql-ws\";\n\n/**\n * Options for the GraphQL WebSocket client\n */\nexport interface WebsocketClientOptions {\n /**\n * The GraphQL endpoint URL for the Portal API\n */\n portalGraphqlEndpoint: string;\n /**\n * The access token for authentication with the Portal API\n */\n accessToken?: string;\n}\n\n/**\n * Creates a GraphQL WebSocket client for the Portal API\n *\n * @param {WebsocketClientOptions} options - The options for the client\n * @returns {Client} The GraphQL WebSocket client\n * @example\n * import { getWebsocketClient } from \"@settlemint/sdk-portal\";\n *\n * const client = getWebsocketClient({\n * portalGraphqlEndpoint: \"https://portal.settlemint.com/graphql\",\n * accessToken: \"your-access-token\",\n * });\n */\nexport function getWebsocketClient({ portalGraphqlEndpoint, accessToken }: WebsocketClientOptions) {\n if (!portalGraphqlEndpoint) {\n throw new Error(\"portalGraphqlEndpoint is required\");\n }\n const graphqlEndpoint = setWsProtocol(new URL(portalGraphqlEndpoint));\n return createClient({\n url: accessToken\n ? `${graphqlEndpoint.protocol}//${graphqlEndpoint.host}/${accessToken}${graphqlEndpoint.pathname}${graphqlEndpoint.search}`\n : graphqlEndpoint.toString(),\n });\n}\n\nfunction setWsProtocol(url: URL) {\n if (url.protocol === \"ws:\" || url.protocol === \"wss:\") {\n return url;\n }\n if (url.protocol === \"http:\") {\n url.protocol = \"ws:\";\n } else {\n url.protocol = \"wss:\";\n }\n return url;\n}\n","import type { FormattedExecutionResult } from \"graphql-ws\";\nimport type { Address, Hex, TransactionReceipt as TransactionReceiptViem } from \"viem\";\nimport { type WebsocketClientOptions, getWebsocketClient } from \"./websocket-client.js\";\n\n/**\n * Represents an event emitted during a transaction execution\n */\nexport interface TransactionEvent {\n /** The name of the event that was emitted */\n eventName: string;\n /** The arguments emitted by the event */\n args: Record<string, unknown>;\n /** Indexed event parameters used for filtering and searching */\n topics: Hex[];\n}\n\n/**\n * Represents the structure of a blockchain transaction receipt\n */\nexport interface TransactionReceipt extends TransactionReceiptViem<string, number, \"Success\" | \"Reverted\"> {\n /** The raw reason for transaction reversion, if applicable */\n revertReason: string;\n /** Human-readable version of the revert reason */\n revertReasonDecoded: string;\n /** Array of events emitted during the transaction */\n events: TransactionEvent[];\n /** The address of the contract deployed in the transaction */\n contractAddress: Address;\n}\n\n/**\n * Represents the structure of a blockchain transaction with its receipt\n */\nexport interface Transaction {\n receipt: TransactionReceipt;\n /** The hash of the transaction (duplicate of receipt.transactionHash) */\n transactionHash: string;\n /** The sender address (duplicate of receipt.from) */\n from: string;\n /** Timestamp when the transaction was created */\n createdAt: string;\n /** The contract address involved in the transaction */\n address: string;\n /** The name of the function called in the transaction */\n functionName: string;\n /** Whether the transaction is a contract deployment */\n isContract: boolean;\n}\n\ninterface GetTransactionResponse {\n getTransaction: Transaction;\n}\n\n/**\n * Options for waiting for a transaction receipt\n */\nexport interface WaitForTransactionReceiptOptions extends WebsocketClientOptions {\n /** Optional timeout in milliseconds before the operation fails */\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 = getWebsocketClient(options);\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","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 * Type representing the different types of wallet verification methods\n */\nexport type WalletVerificationType = \"PINCODE\" | \"OTP\" | \"SECRET_CODES\";\n\n/**\n * Custom error class for challenge-related errors\n */\nexport class WalletVerificationChallengeError 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 id: string;\n name: string;\n verificationId: string;\n verificationType: WalletVerificationType;\n challenge?: {\n salt: string;\n secret: string;\n };\n}\n\n/**\n * Response type for the CreateWalletVerificationChallenge mutation\n */\ninterface CreateWalletVerificationChallengeResponse {\n createWalletVerificationChallenge: 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 */\nexport interface HandleWalletVerificationChallengeOptions<Setup extends AbstractSetupSchema> {\n /** The portal client instance */\n portalClient: GraphQLClient;\n /** The GraphQL query builder */\n portalGraphql: initGraphQLTada<Setup>;\n /** The ID of the verification challenge */\n verificationId: string;\n /** The wallet address to verify */\n userWalletAddress: Address;\n /** The verification code provided by the user */\n code: string | number;\n /** The type of verification being performed */\n verificationType: WalletVerificationType;\n /** Request id which can be added for tracing purposes */\n requestId?: string;\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 {WalletVerificationChallengeError} 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 requestId,\n}: HandleWalletVerificationChallengeOptions<Setup>): Promise<{\n challengeResponse: string;\n challengeId: string;\n}> {\n try {\n const requestHeaders = new Headers();\n if (requestId) {\n requestHeaders.append(\"x-request-id\", requestId);\n }\n const verificationChallenge = await portalClient.request<CreateWalletVerificationChallengeResponse>(\n portalGraphql(`\n mutation CreateWalletVerificationChallenge($userWalletAddress: String!, $verificationId: String!) {\n createWalletVerificationChallenge(\n userWalletAddress: $userWalletAddress\n verificationId: $verificationId\n ) {\n id\n name\n verificationId\n verificationType\n challenge {\n salt\n secret\n }\n }\n }\n `),\n {\n userWalletAddress,\n verificationId,\n },\n requestHeaders,\n );\n\n if (!verificationChallenge.createWalletVerificationChallenge) {\n throw new WalletVerificationChallengeError(\"No verification challenge received\", \"NO_CHALLENGES\");\n }\n\n if (verificationType === \"OTP\") {\n return {\n challengeResponse: code.toString(),\n challengeId: verificationChallenge.createWalletVerificationChallenge.id,\n };\n }\n\n if (verificationType === \"SECRET_CODES\") {\n // Add - separator to the code\n const formattedCode = code.toString().replace(/(.{5})(?=.)/, \"$1-\");\n return {\n challengeResponse: formattedCode,\n challengeId: verificationChallenge.createWalletVerificationChallenge.id,\n };\n }\n\n const { secret, salt } = verificationChallenge.createWalletVerificationChallenge.challenge ?? {};\n\n if (!secret || !salt) {\n throw new WalletVerificationChallengeError(\"Invalid challenge format\", \"INVALID_CHALLENGE\");\n }\n\n const challengeResponse = generateResponse(code.toString(), salt, secret);\n return {\n challengeResponse,\n challengeId: verificationChallenge.createWalletVerificationChallenge.id,\n };\n } catch (error) {\n if (error instanceof WalletVerificationChallengeError) {\n throw error;\n }\n throw new WalletVerificationChallengeError(\n \"Failed to process wallet verification challenge\",\n \"CHALLENGE_PROCESSING_ERROR\",\n );\n }\n}\n","import { appendHeaders } from \"@settlemint/sdk-utils/http\";\nimport { 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.optional(),\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: appendHeaders(clientOptions?.headers, { \"x-auth-token\": validatedOptions.accessToken }),\n }),\n graphql,\n };\n}\n\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport { readFragment } from \"gql.tada\";\nexport {\n type Transaction,\n type TransactionEvent,\n type TransactionReceipt,\n type WaitForTransactionReceiptOptions,\n waitForTransactionReceipt,\n} from \"./utils/wait-for-transaction-receipt.js\";\nexport {\n type HandleWalletVerificationChallengeOptions,\n handleWalletVerificationChallenge,\n WalletVerificationChallengeError,\n type WalletVerificationType,\n} from \"./utils/wallet-verification-challenge.js\";\nexport { getWebsocketClient, type WebsocketClientOptions } from \"./utils/websocket-client.js\";\n"],"mappings":"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"}
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.5.13",
4
+ "version": "2.5.14-pr16f805ec",
5
5
  "type": "module",
6
6
  "private": false,
7
7
  "license": "FSL-1.1-MIT",
@@ -59,7 +59,7 @@
59
59
  "dependencies": {
60
60
  "gql.tada": "^1",
61
61
  "graphql-ws": "^6",
62
- "@settlemint/sdk-utils": "2.5.13",
62
+ "@settlemint/sdk-utils": "2.5.14-pr16f805ec",
63
63
  "graphql-request": "^7",
64
64
  "zod": "^4"
65
65
  },