@multiplatform.one/wallet 7.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/README.md +8 -0
  2. package/dist/cjs/SiweKeycloakProvider.cjs +273 -0
  3. package/dist/cjs/SiweKeycloakProvider.native.js +309 -0
  4. package/dist/cjs/SiweKeycloakProvider.native.js.map +1 -0
  5. package/dist/cjs/base64.cjs +51 -0
  6. package/dist/cjs/base64.native.js +55 -0
  7. package/dist/cjs/base64.native.js.map +1 -0
  8. package/dist/cjs/base64.spec.cjs +57 -0
  9. package/dist/cjs/base64.spec.native.js +79 -0
  10. package/dist/cjs/base64.spec.native.js.map +1 -0
  11. package/dist/cjs/context.cjs +29 -0
  12. package/dist/cjs/context.native.js +32 -0
  13. package/dist/cjs/context.native.js.map +1 -0
  14. package/dist/cjs/hooks/context.cjs +29 -0
  15. package/dist/cjs/hooks/context.native.js +32 -0
  16. package/dist/cjs/hooks/context.native.js.map +1 -0
  17. package/dist/cjs/hooks/index.cjs +20 -0
  18. package/dist/cjs/hooks/index.native.js +23 -0
  19. package/dist/cjs/hooks/index.native.js.map +1 -0
  20. package/dist/cjs/hooks/useSiweKeycloak.cjs +61 -0
  21. package/dist/cjs/hooks/useSiweKeycloak.native.js +64 -0
  22. package/dist/cjs/hooks/useSiweKeycloak.native.js.map +1 -0
  23. package/dist/cjs/index.cjs +133 -0
  24. package/dist/cjs/index.native.js +189 -0
  25. package/dist/cjs/index.native.js.map +1 -0
  26. package/dist/cjs/render.cjs +78 -0
  27. package/dist/cjs/render.native.js +82 -0
  28. package/dist/cjs/render.native.js.map +1 -0
  29. package/dist/cjs/siwe.cjs +76 -0
  30. package/dist/cjs/siwe.native.js +94 -0
  31. package/dist/cjs/siwe.native.js.map +1 -0
  32. package/dist/cjs/types.cjs +18 -0
  33. package/dist/cjs/types.native.js +21 -0
  34. package/dist/cjs/types.native.js.map +1 -0
  35. package/dist/cjs/util.cjs +53 -0
  36. package/dist/cjs/util.native.js +56 -0
  37. package/dist/cjs/util.native.js.map +1 -0
  38. package/dist/cjs/util.spec.cjs +53 -0
  39. package/dist/cjs/util.spec.native.js +62 -0
  40. package/dist/cjs/util.spec.native.js.map +1 -0
  41. package/dist/esm/SiweKeycloakProvider.mjs +237 -0
  42. package/dist/esm/SiweKeycloakProvider.mjs.map +1 -0
  43. package/dist/esm/SiweKeycloakProvider.native.js +270 -0
  44. package/dist/esm/SiweKeycloakProvider.native.js.map +1 -0
  45. package/dist/esm/base64.mjs +26 -0
  46. package/dist/esm/base64.mjs.map +1 -0
  47. package/dist/esm/base64.native.js +27 -0
  48. package/dist/esm/base64.native.js.map +1 -0
  49. package/dist/esm/base64.spec.mjs +58 -0
  50. package/dist/esm/base64.spec.mjs.map +1 -0
  51. package/dist/esm/base64.spec.native.js +77 -0
  52. package/dist/esm/base64.spec.native.js.map +1 -0
  53. package/dist/esm/context.mjs +4 -0
  54. package/dist/esm/context.mjs.map +1 -0
  55. package/dist/esm/context.native.js +4 -0
  56. package/dist/esm/context.native.js.map +1 -0
  57. package/dist/esm/hooks/context.mjs +4 -0
  58. package/dist/esm/hooks/context.mjs.map +1 -0
  59. package/dist/esm/hooks/context.native.js +4 -0
  60. package/dist/esm/hooks/context.native.js.map +1 -0
  61. package/dist/esm/hooks/index.mjs +2 -0
  62. package/dist/esm/hooks/index.mjs.map +1 -0
  63. package/dist/esm/hooks/index.native.js +2 -0
  64. package/dist/esm/hooks/index.native.js.map +1 -0
  65. package/dist/esm/hooks/useSiweKeycloak.mjs +36 -0
  66. package/dist/esm/hooks/useSiweKeycloak.mjs.map +1 -0
  67. package/dist/esm/hooks/useSiweKeycloak.native.js +36 -0
  68. package/dist/esm/hooks/useSiweKeycloak.native.js.map +1 -0
  69. package/dist/esm/index.mjs +107 -0
  70. package/dist/esm/index.mjs.map +1 -0
  71. package/dist/esm/index.native.js +160 -0
  72. package/dist/esm/index.native.js.map +1 -0
  73. package/dist/esm/render.mjs +42 -0
  74. package/dist/esm/render.mjs.map +1 -0
  75. package/dist/esm/render.native.js +43 -0
  76. package/dist/esm/render.native.js.map +1 -0
  77. package/dist/esm/siwe.mjs +51 -0
  78. package/dist/esm/siwe.mjs.map +1 -0
  79. package/dist/esm/siwe.native.js +66 -0
  80. package/dist/esm/siwe.native.js.map +1 -0
  81. package/dist/esm/types.mjs +2 -0
  82. package/dist/esm/types.mjs.map +1 -0
  83. package/dist/esm/types.native.js +2 -0
  84. package/dist/esm/types.native.js.map +1 -0
  85. package/dist/esm/util.mjs +27 -0
  86. package/dist/esm/util.mjs.map +1 -0
  87. package/dist/esm/util.native.js +27 -0
  88. package/dist/esm/util.native.js.map +1 -0
  89. package/dist/esm/util.spec.mjs +54 -0
  90. package/dist/esm/util.spec.mjs.map +1 -0
  91. package/dist/esm/util.spec.native.js +60 -0
  92. package/dist/esm/util.spec.native.js.map +1 -0
  93. package/package.json +81 -0
  94. package/src/SiweKeycloakProvider.tsx +297 -0
  95. package/src/base64.spec.ts +65 -0
  96. package/src/base64.ts +26 -0
  97. package/src/context.ts +10 -0
  98. package/src/hooks/context.ts +10 -0
  99. package/src/hooks/index.ts +1 -0
  100. package/src/hooks/useSiweKeycloak.ts +23 -0
  101. package/src/index.ts +127 -0
  102. package/src/main/java/com/bitspur/keycloak/siwe/Errors.java +21 -0
  103. package/src/main/java/com/bitspur/keycloak/siwe/LiteAuthenticationService.java +167 -0
  104. package/src/main/java/com/bitspur/keycloak/siwe/SiweCredentials.java +36 -0
  105. package/src/main/java/com/bitspur/keycloak/siwe/SiweSession.java +36 -0
  106. package/src/main/java/com/bitspur/keycloak/siwe/SiweUtil.java +599 -0
  107. package/src/main/java/com/bitspur/keycloak/siwe/Token.java +85 -0
  108. package/src/main/java/com/bitspur/keycloak/siwe/authenticators/browser/SiweBrowserAuthenticator.java +109 -0
  109. package/src/main/java/com/bitspur/keycloak/siwe/authenticators/browser/SiweBrowserAuthenticatorFactory.java +93 -0
  110. package/src/main/java/com/bitspur/keycloak/siwe/authenticators/directgrant/SiweDirectGrantAuthenticator.java +153 -0
  111. package/src/main/java/com/bitspur/keycloak/siwe/authenticators/directgrant/SiweDirectGrantAuthenticatorFactory.java +93 -0
  112. package/src/main/java/com/bitspur/keycloak/siwe/jpa/nonce/SiweNonce.java +95 -0
  113. package/src/main/java/com/bitspur/keycloak/siwe/jpa/nonce/SiweNonceJpaEntityProvider.java +82 -0
  114. package/src/main/java/com/bitspur/keycloak/siwe/jpa/nonce/SiweNonceJpaEntityProviderFactory.java +46 -0
  115. package/src/main/java/com/bitspur/keycloak/siwe/jpa/wallet/SiweWalletAddress.java +103 -0
  116. package/src/main/java/com/bitspur/keycloak/siwe/jpa/wallet/SiweWalletJpaEntityProvider.java +43 -0
  117. package/src/main/java/com/bitspur/keycloak/siwe/jpa/wallet/SiweWalletJpaEntityProviderFactory.java +46 -0
  118. package/src/main/java/com/bitspur/keycloak/siwe/protocol/SiweWalletProtocolMapper.java +85 -0
  119. package/src/main/java/com/bitspur/keycloak/siwe/resource/SiweResource.java +210 -0
  120. package/src/main/java/com/bitspur/keycloak/siwe/resource/SiweResourceProvider.java +34 -0
  121. package/src/main/java/com/bitspur/keycloak/siwe/resource/SiweResourceProviderFactory.java +46 -0
  122. package/src/main/java/com/bitspur/keycloak/siwe/siu/SiuCredentials.java +52 -0
  123. package/src/main/java/com/bitspur/keycloak/siwe/siu/SiuMessage.java +362 -0
  124. package/src/main/java/com/bitspur/keycloak/siwe/siu/SiuParseException.java +23 -0
  125. package/src/main/java/com/bitspur/keycloak/siwe/siu/SiuUtil.java +547 -0
  126. package/src/main/java/com/bitspur/keycloak/siwe/siu/authenticators/browser/SiuBrowserAuthenticator.java +112 -0
  127. package/src/main/java/com/bitspur/keycloak/siwe/siu/authenticators/browser/SiuBrowserAuthenticatorFactory.java +96 -0
  128. package/src/main/java/com/bitspur/keycloak/siwe/siu/authenticators/directgrant/SiuDirectGrantAuthenticator.java +169 -0
  129. package/src/main/java/com/bitspur/keycloak/siwe/siu/authenticators/directgrant/SiuDirectGrantAuthenticatorFactory.java +96 -0
  130. package/src/main/java/com/bitspur/keycloak/siwe/siu/resource/SiuResource.java +244 -0
  131. package/src/main/java/com/bitspur/keycloak/siwe/siu/resource/SiuResourceProvider.java +34 -0
  132. package/src/main/java/com/bitspur/keycloak/siwe/siu/resource/SiuResourceProviderFactory.java +48 -0
  133. package/src/main/java/com/bitspur/keycloak/siwe/siws/SiwsCredentials.java +52 -0
  134. package/src/main/java/com/bitspur/keycloak/siwe/siws/SiwsMessage.java +362 -0
  135. package/src/main/java/com/bitspur/keycloak/siwe/siws/SiwsParseException.java +23 -0
  136. package/src/main/java/com/bitspur/keycloak/siwe/siws/SiwsUtil.java +564 -0
  137. package/src/main/java/com/bitspur/keycloak/siwe/siws/authenticators/browser/SiwsBrowserAuthenticator.java +112 -0
  138. package/src/main/java/com/bitspur/keycloak/siwe/siws/authenticators/browser/SiwsBrowserAuthenticatorFactory.java +96 -0
  139. package/src/main/java/com/bitspur/keycloak/siwe/siws/authenticators/directgrant/SiwsDirectGrantAuthenticator.java +169 -0
  140. package/src/main/java/com/bitspur/keycloak/siwe/siws/authenticators/directgrant/SiwsDirectGrantAuthenticatorFactory.java +96 -0
  141. package/src/main/java/com/bitspur/keycloak/siwe/siws/resource/SiwsResource.java +244 -0
  142. package/src/main/java/com/bitspur/keycloak/siwe/siws/resource/SiwsResourceProvider.java +34 -0
  143. package/src/main/java/com/bitspur/keycloak/siwe/siws/resource/SiwsResourceProviderFactory.java +48 -0
  144. package/src/main/resources/META-INF/keycloak-themes.json +8 -0
  145. package/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory +6 -0
  146. package/src/main/resources/META-INF/services/org.keycloak.connections.jpa.entityprovider.JpaEntityProviderFactory +2 -0
  147. package/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper +1 -0
  148. package/src/main/resources/META-INF/services/org.keycloak.services.resource.RealmResourceProviderFactory +3 -0
  149. package/src/main/resources/META-INF/siwe-nonce-changelog.xml +29 -0
  150. package/src/main/resources/META-INF/siwe-wallet-changelog.xml +46 -0
  151. package/src/render.tsx +47 -0
  152. package/src/siwe.tsx +57 -0
  153. package/src/types.ts +6 -0
  154. package/src/util.spec.ts +72 -0
  155. package/src/util.ts +28 -0
@@ -0,0 +1,6 @@
1
+ com.bitspur.keycloak.siwe.authenticators.browser.SiweBrowserAuthenticatorFactory
2
+ com.bitspur.keycloak.siwe.authenticators.directgrant.SiweDirectGrantAuthenticatorFactory
3
+ com.bitspur.keycloak.siwe.siws.authenticators.browser.SiwsBrowserAuthenticatorFactory
4
+ com.bitspur.keycloak.siwe.siws.authenticators.directgrant.SiwsDirectGrantAuthenticatorFactory
5
+ com.bitspur.keycloak.siwe.siu.authenticators.browser.SiuBrowserAuthenticatorFactory
6
+ com.bitspur.keycloak.siwe.siu.authenticators.directgrant.SiuDirectGrantAuthenticatorFactory
@@ -0,0 +1,2 @@
1
+ com.bitspur.keycloak.siwe.jpa.nonce.SiweNonceJpaEntityProviderFactory
2
+ com.bitspur.keycloak.siwe.jpa.wallet.SiweWalletJpaEntityProviderFactory
@@ -0,0 +1 @@
1
+ com.bitspur.keycloak.siwe.protocol.SiweWalletProtocolMapper
@@ -0,0 +1,3 @@
1
+ com.bitspur.keycloak.siwe.resource.SiweResourceProviderFactory
2
+ com.bitspur.keycloak.siwe.siws.resource.SiwsResourceProviderFactory
3
+ com.bitspur.keycloak.siwe.siu.resource.SiuResourceProviderFactory
@@ -0,0 +1,29 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
3
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+ xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
5
+ <changeSet author="erik.mulder@docdatapayments.com" id="example-1.0">
6
+
7
+ <createTable tableName="SIWE_NONCE">
8
+ <column name="ID" type="BIGINT" autoIncrement="true">
9
+ <constraints nullable="false" primaryKey="true" />
10
+ </column>
11
+ <column name="NONCE_KEY" type="VARCHAR(255)">
12
+ <constraints nullable="false" />
13
+ </column>
14
+ <column name="NONCE" type="VARCHAR(255)">
15
+ <constraints nullable="true" />
16
+ </column>
17
+ <column name="REALM_ID" type="VARCHAR(36)">
18
+ <constraints nullable="false" />
19
+ </column>
20
+ <column name="CREATED_AT" type="TIMESTAMP DEFAULT CURRENT_TIMESTAMP">
21
+ <constraints nullable="false" />
22
+ </column>
23
+ <column name="UPDATED_AT" type="TIMESTAMP DEFAULT CURRENT_TIMESTAMP">
24
+ <constraints nullable="false" />
25
+ </column>
26
+ </createTable>
27
+
28
+ </changeSet>
29
+ </databaseChangeLog>
@@ -0,0 +1,46 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
3
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+ xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
5
+ <changeSet author="clay.risser" id="siwe-wallet-1.0">
6
+ <createTable tableName="SIWE_WALLET_ADDRESS">
7
+ <column name="ID" type="BIGINT" autoIncrement="true">
8
+ <constraints nullable="false" primaryKey="true" />
9
+ </column>
10
+ <column name="ADDRESS" type="VARCHAR(255)">
11
+ <constraints nullable="false" />
12
+ </column>
13
+ <column name="ADDRESS_TYPE" type="VARCHAR(50)">
14
+ <constraints nullable="false" />
15
+ </column>
16
+ <column name="USER_ID" type="VARCHAR(36)">
17
+ <constraints nullable="false" />
18
+ </column>
19
+ <column name="REALM_ID" type="VARCHAR(36)">
20
+ <constraints nullable="false" />
21
+ </column>
22
+ <column name="CREATED_AT" type="TIMESTAMP DEFAULT CURRENT_TIMESTAMP">
23
+ <constraints nullable="false" />
24
+ </column>
25
+ <column name="UPDATED_AT" type="TIMESTAMP DEFAULT CURRENT_TIMESTAMP">
26
+ <constraints nullable="false" />
27
+ </column>
28
+ </createTable>
29
+
30
+ <addUniqueConstraint
31
+ tableName="SIWE_WALLET_ADDRESS"
32
+ columnNames="ADDRESS,REALM_ID"
33
+ constraintName="UK_SIWE_WALLET_ADDRESS_UNIQUE" />
34
+
35
+ <createIndex tableName="SIWE_WALLET_ADDRESS" indexName="IDX_SIWE_WALLET_ADDRESS">
36
+ <column name="ADDRESS" />
37
+ <column name="ADDRESS_TYPE" />
38
+ <column name="REALM_ID" />
39
+ </createIndex>
40
+
41
+ <createIndex tableName="SIWE_WALLET_ADDRESS" indexName="IDX_SIWE_WALLET_USER">
42
+ <column name="USER_ID" />
43
+ <column name="REALM_ID" />
44
+ </createIndex>
45
+ </changeSet>
46
+ </databaseChangeLog>
package/src/render.tsx ADDED
@@ -0,0 +1,47 @@
1
+ import React from "react";
2
+ import { createRoot } from "react-dom/client";
3
+ import { SiweKeycloakProvider } from ".";
4
+ import type { SiweProps } from "./siwe";
5
+ import { Siwe } from "./siwe";
6
+ import type { SiweKeycloakProviderProps } from "./index";
7
+
8
+ export interface RenderOptions extends SiweKeycloakProviderProps, SiweProps {
9
+ element?: HTMLElement | null;
10
+ }
11
+
12
+ export function render({
13
+ element,
14
+ onAddresses,
15
+ onSetClient,
16
+ onSetConnect,
17
+ onSetOpenAbout,
18
+ onSetOpenOnboarding,
19
+ onSetOpenProfile,
20
+ onSetOpenSIWE,
21
+ onSetOpenSwitchNetworks,
22
+ onSetSignOut,
23
+ onSetWalletClient,
24
+ setTokens: _setTokens,
25
+ ...props
26
+ }: RenderOptions) {
27
+ if (!element) element = document.createElement("div");
28
+ if (!element) return;
29
+ window.React = React;
30
+ const root = createRoot(element);
31
+ root.render(
32
+ <SiweKeycloakProvider {...props}>
33
+ <Siwe
34
+ onAddresses={onAddresses}
35
+ onSetClient={onSetClient}
36
+ onSetConnect={onSetConnect}
37
+ onSetOpenAbout={onSetOpenAbout}
38
+ onSetOpenOnboarding={onSetOpenOnboarding}
39
+ onSetOpenProfile={onSetOpenProfile}
40
+ onSetOpenSIWE={onSetOpenSIWE}
41
+ onSetOpenSwitchNetworks={onSetOpenSwitchNetworks}
42
+ onSetSignOut={onSetSignOut}
43
+ onSetWalletClient={onSetWalletClient}
44
+ />
45
+ </SiweKeycloakProvider>,
46
+ );
47
+ }
package/src/siwe.tsx ADDED
@@ -0,0 +1,57 @@
1
+ import type { GetWalletClientData } from "@wagmi/core/query";
2
+ import { useEffect } from "react";
3
+ import type { Address } from "viem";
4
+ import { type UseClientReturnType, useAccount, useClient, useWalletClient } from "wagmi";
5
+ import { useSiweKeycloak } from "./hooks/useSiweKeycloak";
6
+
7
+ export interface SiweProps {
8
+ onSetOpenAbout: (openAbout: () => void) => void;
9
+ onSetOpenOnboarding: (openOnboarding: () => void) => void;
10
+ onSetOpenProfile: (openProfile: () => void) => void;
11
+ onSetOpenSIWE: (openSIWE: (triggerSIWE?: boolean) => void) => void;
12
+ onSetOpenSwitchNetworks: (openSwitchNetworks: () => void) => void;
13
+ onSetSignOut: (signOut: () => void) => void;
14
+ onSetClient: (client: UseClientReturnType) => void;
15
+ onSetConnect: (connect: () => void) => void;
16
+ onSetWalletClient: (walletClient: GetWalletClientData<any, any>) => void;
17
+ onAddresses?: (addresses: readonly [Address, ...Address[]] | readonly Address[]) => void;
18
+ }
19
+
20
+ export function Siwe({
21
+ onSetOpenAbout,
22
+ onSetOpenOnboarding,
23
+ onSetOpenProfile,
24
+ onSetOpenSIWE,
25
+ onSetOpenSwitchNetworks,
26
+ onSetSignOut,
27
+ onSetClient,
28
+ onSetWalletClient,
29
+ onSetConnect,
30
+ onAddresses,
31
+ }: SiweProps) {
32
+ const { addresses } = useAccount();
33
+ const { data: walletClient } = useWalletClient();
34
+ const client = useClient();
35
+ const { openAbout, openOnboarding, openProfile, openSIWE, openSwitchNetworks, signOut, connect } =
36
+ useSiweKeycloak();
37
+ useEffect(() => onSetOpenAbout(openAbout), [onSetOpenAbout, openAbout]);
38
+ useEffect(() => onSetOpenOnboarding(openOnboarding), [onSetOpenOnboarding, openOnboarding]);
39
+ useEffect(() => onSetOpenProfile(openProfile), [onSetOpenProfile, openProfile]);
40
+ useEffect(() => onSetOpenSIWE(openSIWE), [onSetOpenSIWE, openSIWE]);
41
+ useEffect(
42
+ () => onSetOpenSwitchNetworks(openSwitchNetworks),
43
+ [onSetOpenSwitchNetworks, openSwitchNetworks],
44
+ );
45
+ useEffect(() => onSetSignOut(signOut), [onSetSignOut, signOut]);
46
+ useEffect(() => {
47
+ if (walletClient) onSetWalletClient(walletClient);
48
+ }, [onSetWalletClient, walletClient]);
49
+ useEffect(() => {
50
+ if (client) onSetClient(client);
51
+ }, [onSetClient, client]);
52
+ useEffect(() => {
53
+ onSetConnect(connect);
54
+ }, [onSetConnect, connect]);
55
+ useEffect(() => onAddresses?.(addresses || []), [onAddresses, addresses?.length]);
56
+ return null;
57
+ }
package/src/types.ts ADDED
@@ -0,0 +1,6 @@
1
+ export interface KeycloakConfig {
2
+ baseUrl: string;
3
+ clientId: string;
4
+ realm: string;
5
+ scope: string | string[];
6
+ }
@@ -0,0 +1,72 @@
1
+ import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
2
+ import { getNonce, createMessage } from "./util";
3
+
4
+ describe("getNonce", () => {
5
+ beforeEach(() => {
6
+ vi.stubGlobal(
7
+ "fetch",
8
+ vi.fn().mockResolvedValue({
9
+ ok: true,
10
+ text: () => Promise.resolve("abc123nonce"),
11
+ }),
12
+ );
13
+ });
14
+
15
+ afterEach(() => {
16
+ vi.restoreAllMocks();
17
+ });
18
+
19
+ it("fetches nonce from the keycloak SIWE URL", async () => {
20
+ const nonce = await getNonce("https://auth.example.com/siwe");
21
+ expect(fetch).toHaveBeenCalledWith("https://auth.example.com/siwe/nonce", {
22
+ credentials: "include",
23
+ });
24
+ expect(nonce).toBe("abc123nonce");
25
+ });
26
+
27
+ it("throws when response is not ok", async () => {
28
+ vi.stubGlobal(
29
+ "fetch",
30
+ vi.fn().mockResolvedValue({
31
+ ok: false,
32
+ text: () => Promise.resolve(""),
33
+ }),
34
+ );
35
+ await expect(getNonce("https://auth.example.com/siwe")).rejects.toThrow("failed to get nonce");
36
+ });
37
+
38
+ it("throws when response body is empty", async () => {
39
+ vi.stubGlobal(
40
+ "fetch",
41
+ vi.fn().mockResolvedValue({
42
+ ok: true,
43
+ text: () => Promise.resolve(""),
44
+ }),
45
+ );
46
+ await expect(getNonce("https://auth.example.com/siwe")).rejects.toThrow("failed to get nonce");
47
+ });
48
+ });
49
+
50
+ describe("createMessage", () => {
51
+ it("throws when window is undefined (non-browser)", async () => {
52
+ const origWindow = globalThis.window;
53
+ // @ts-expect-error simulating SSR
54
+ delete globalThis.window;
55
+ try {
56
+ await expect(
57
+ createMessage("nonce123", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", 1),
58
+ ).rejects.toThrow("createMessage requires browser context");
59
+ } finally {
60
+ globalThis.window = origWindow;
61
+ }
62
+ });
63
+
64
+ it("creates a SIWE message using browser location", async () => {
65
+ const addr = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" as `0x${string}`;
66
+ const message = await createMessage("nonce123", addr, 1);
67
+ expect(message).toContain("Sign in With Ethereum.");
68
+ expect(message).toContain("nonce123");
69
+ expect(message).toContain(addr);
70
+ expect(message).toContain("Chain ID: 1");
71
+ });
72
+ });
package/src/util.ts ADDED
@@ -0,0 +1,28 @@
1
+ import { SiweMessage } from "siwe";
2
+ import type { Address } from "viem";
3
+
4
+ export async function getNonce(keycloakSiweUrl: string) {
5
+ const res = await fetch(`${keycloakSiweUrl}/nonce`, {
6
+ credentials: "include",
7
+ });
8
+ if (res.ok) {
9
+ const data = await res.text();
10
+ if (data?.length) return data;
11
+ }
12
+ throw new Error("failed to get nonce");
13
+ }
14
+
15
+ export async function createMessage(nonce: string, address: Address, chainId: number) {
16
+ if (typeof window === "undefined") {
17
+ throw new Error("createMessage requires browser context");
18
+ }
19
+ return new SiweMessage({
20
+ version: "1",
21
+ domain: window.location.host,
22
+ uri: window.location.origin,
23
+ address,
24
+ chainId,
25
+ nonce,
26
+ statement: "Sign in With Ethereum.",
27
+ }).prepareMessage();
28
+ }