@arcblock/did-connect-react 3.1.0

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 (183) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +134 -0
  3. package/lib/Address/index.js +4 -0
  4. package/lib/Avatar/index.js +4 -0
  5. package/lib/Button/index.js +17 -0
  6. package/lib/Connect/assets/locale.js +143 -0
  7. package/lib/Connect/assets/login-bg.png +0 -0
  8. package/lib/Connect/assets/login-slogan.js +9 -0
  9. package/lib/Connect/components/action-button.js +26 -0
  10. package/lib/Connect/components/app-tips.js +132 -0
  11. package/lib/Connect/components/auto-height.js +31 -0
  12. package/lib/Connect/components/back-button.js +24 -0
  13. package/lib/Connect/components/connect-status.js +263 -0
  14. package/lib/Connect/components/did-connect-title.js +126 -0
  15. package/lib/Connect/components/download-tips.js +52 -0
  16. package/lib/Connect/components/loading.js +26 -0
  17. package/lib/Connect/components/login-item/connect-choose-list.js +249 -0
  18. package/lib/Connect/components/login-item/login-method-item.js +129 -0
  19. package/lib/Connect/components/login-item/mobile-login-item.js +114 -0
  20. package/lib/Connect/components/login-item/passkey-login-item.js +44 -0
  21. package/lib/Connect/components/login-item/web-login-item.js +97 -0
  22. package/lib/Connect/components/mask-overlay.js +34 -0
  23. package/lib/Connect/components/refresh-overlay.js +57 -0
  24. package/lib/Connect/components/switch-app.js +70 -0
  25. package/lib/Connect/contexts/state.js +142 -0
  26. package/lib/Connect/fullpage.js +5 -0
  27. package/lib/Connect/hooks/auth-url.js +23 -0
  28. package/lib/Connect/hooks/method-list.js +46 -0
  29. package/lib/Connect/hooks/page-show.js +17 -0
  30. package/lib/Connect/hooks/security.js +27 -0
  31. package/lib/Connect/hooks/token.js +305 -0
  32. package/lib/Connect/hooks/use-apps.js +19 -0
  33. package/lib/Connect/hooks/use-quick-connect.js +97 -0
  34. package/lib/Connect/index.js +498 -0
  35. package/lib/Connect/landing-page.js +5 -0
  36. package/lib/Connect/plugins/email/index.js +62 -0
  37. package/lib/Connect/plugins/email/list-item.js +28 -0
  38. package/lib/Connect/plugins/email/placeholder.js +283 -0
  39. package/lib/Connect/plugins/index.js +4 -0
  40. package/lib/Connect/use-connect.js +164 -0
  41. package/lib/Connect/with-blocklet.js +15 -0
  42. package/lib/Connect/with-bridge-call.js +108 -0
  43. package/lib/Federated/context.js +61 -0
  44. package/lib/Federated/index.js +7 -0
  45. package/lib/Logo/index.js +4 -0
  46. package/lib/OAuth/context.js +234 -0
  47. package/lib/OAuth/guest.svg.js +5 -0
  48. package/lib/OAuth/index.js +7 -0
  49. package/lib/OAuth/passport-switcher.js +114 -0
  50. package/lib/Passkey/actions.js +165 -0
  51. package/lib/Passkey/constants.js +4 -0
  52. package/lib/Passkey/context.js +266 -0
  53. package/lib/Passkey/dialog.js +277 -0
  54. package/lib/Passkey/icon.js +13 -0
  55. package/lib/Passkey/index.js +9 -0
  56. package/lib/Service/index.js +62 -0
  57. package/lib/Session/assets/did-spaces-guide-cover.svg.js +135 -0
  58. package/lib/Session/assets/did-spaces-guide-icon.svg.js +9 -0
  59. package/lib/Session/context.js +5 -0
  60. package/lib/Session/did-spaces-guide.js +136 -0
  61. package/lib/Session/hooks/use-federated.js +64 -0
  62. package/lib/Session/hooks/use-mobile.js +8 -0
  63. package/lib/Session/hooks/use-protected-routes.js +11 -0
  64. package/lib/Session/hooks/use-session-token.js +169 -0
  65. package/lib/Session/hooks/use-verify.js +45 -0
  66. package/lib/Session/index.js +896 -0
  67. package/lib/Session/libs/constants.js +15 -0
  68. package/lib/Session/libs/did-spaces.js +10 -0
  69. package/lib/Session/libs/federated.js +42 -0
  70. package/lib/Session/libs/index.js +15 -0
  71. package/lib/Session/libs/locales.js +161 -0
  72. package/lib/Session/libs/login-mobile.js +55 -0
  73. package/lib/Session/window-focus-aware.js +17 -0
  74. package/lib/SessionManager/index.js +4 -0
  75. package/lib/Storage/engine/cookie.js +21 -0
  76. package/lib/Storage/engine/local-storage.js +36 -0
  77. package/lib/Storage/index.js +23 -0
  78. package/lib/User/index.js +6 -0
  79. package/lib/User/use-did.js +59 -0
  80. package/lib/User/wrap-did.js +13 -0
  81. package/lib/WebWalletSWKeeper/index.js +5 -0
  82. package/lib/constant.js +22 -0
  83. package/lib/error.js +8 -0
  84. package/lib/hooks/use-locale.js +7 -0
  85. package/lib/index.js +33 -0
  86. package/lib/locales/en.js +17 -0
  87. package/lib/locales/index.js +10 -0
  88. package/lib/locales/zh.js +17 -0
  89. package/lib/package.json.js +7 -0
  90. package/lib/types.d.ts +355 -0
  91. package/lib/utils.js +214 -0
  92. package/package.json +84 -0
  93. package/src/Address/index.jsx +2 -0
  94. package/src/Avatar/index.jsx +2 -0
  95. package/src/Button/Button.stories.jsx +7 -0
  96. package/src/Button/index.jsx +21 -0
  97. package/src/Connect/Connect.stories.jsx +34 -0
  98. package/src/Connect/assets/locale.js +145 -0
  99. package/src/Connect/assets/login-bg.png +0 -0
  100. package/src/Connect/assets/login-slogan.js +7 -0
  101. package/src/Connect/components/action-button.jsx +22 -0
  102. package/src/Connect/components/app-tips.jsx +156 -0
  103. package/src/Connect/components/auto-height.jsx +38 -0
  104. package/src/Connect/components/back-button.jsx +23 -0
  105. package/src/Connect/components/connect-status.jsx +259 -0
  106. package/src/Connect/components/did-connect-title.jsx +106 -0
  107. package/src/Connect/components/download-tips.jsx +55 -0
  108. package/src/Connect/components/loading.jsx +25 -0
  109. package/src/Connect/components/login-item/connect-choose-list.jsx +304 -0
  110. package/src/Connect/components/login-item/login-method-item.jsx +118 -0
  111. package/src/Connect/components/login-item/mobile-login-item.jsx +179 -0
  112. package/src/Connect/components/login-item/passkey-login-item.jsx +52 -0
  113. package/src/Connect/components/login-item/web-login-item.jsx +149 -0
  114. package/src/Connect/components/mask-overlay.jsx +32 -0
  115. package/src/Connect/components/refresh-overlay.jsx +52 -0
  116. package/src/Connect/components/switch-app.jsx +69 -0
  117. package/src/Connect/contexts/state.jsx +219 -0
  118. package/src/Connect/fullpage.jsx +3 -0
  119. package/src/Connect/hooks/auth-url.js +31 -0
  120. package/src/Connect/hooks/method-list.js +121 -0
  121. package/src/Connect/hooks/page-show.js +24 -0
  122. package/src/Connect/hooks/security.js +40 -0
  123. package/src/Connect/hooks/token.js +639 -0
  124. package/src/Connect/hooks/use-apps.js +69 -0
  125. package/src/Connect/hooks/use-quick-connect.js +130 -0
  126. package/src/Connect/index.jsx +600 -0
  127. package/src/Connect/landing-page.jsx +3 -0
  128. package/src/Connect/plugins/email/index.jsx +82 -0
  129. package/src/Connect/plugins/email/list-item.jsx +31 -0
  130. package/src/Connect/plugins/email/placeholder.jsx +365 -0
  131. package/src/Connect/plugins/index.js +2 -0
  132. package/src/Connect/use-connect.jsx +321 -0
  133. package/src/Connect/with-blocklet.jsx +26 -0
  134. package/src/Connect/with-bridge-call.jsx +138 -0
  135. package/src/Federated/context.jsx +93 -0
  136. package/src/Federated/index.jsx +1 -0
  137. package/src/Logo/index.jsx +2 -0
  138. package/src/OAuth/context.jsx +346 -0
  139. package/src/OAuth/guest.svg +20 -0
  140. package/src/OAuth/index.jsx +1 -0
  141. package/src/OAuth/passport-switcher.jsx +133 -0
  142. package/src/Passkey/actions.jsx +212 -0
  143. package/src/Passkey/constants.js +2 -0
  144. package/src/Passkey/context.jsx +381 -0
  145. package/src/Passkey/dialog.jsx +391 -0
  146. package/src/Passkey/icon.jsx +10 -0
  147. package/src/Passkey/index.jsx +2 -0
  148. package/src/Service/index.jsx +96 -0
  149. package/src/Session/assets/did-spaces-guide-cover.svg +128 -0
  150. package/src/Session/assets/did-spaces-guide-icon.svg +7 -0
  151. package/src/Session/context.jsx +7 -0
  152. package/src/Session/did-spaces-guide.jsx +173 -0
  153. package/src/Session/hooks/use-federated.js +88 -0
  154. package/src/Session/hooks/use-mobile.jsx +6 -0
  155. package/src/Session/hooks/use-protected-routes.js +16 -0
  156. package/src/Session/hooks/use-session-token.js +365 -0
  157. package/src/Session/hooks/use-verify.jsx +76 -0
  158. package/src/Session/index.jsx +1687 -0
  159. package/src/Session/libs/constants.js +14 -0
  160. package/src/Session/libs/did-spaces.js +38 -0
  161. package/src/Session/libs/federated.js +79 -0
  162. package/src/Session/libs/index.js +5 -0
  163. package/src/Session/libs/locales.js +160 -0
  164. package/src/Session/libs/login-mobile.js +80 -0
  165. package/src/Session/window-focus-aware.jsx +28 -0
  166. package/src/SessionManager/index.jsx +2 -0
  167. package/src/Storage/engine/cookie.js +23 -0
  168. package/src/Storage/engine/local-storage.js +55 -0
  169. package/src/Storage/index.js +25 -0
  170. package/src/User/index.js +4 -0
  171. package/src/User/use-did.js +80 -0
  172. package/src/User/wrap-did.jsx +18 -0
  173. package/src/WebWalletSWKeeper/index.jsx +3 -0
  174. package/src/constant.js +26 -0
  175. package/src/error.js +6 -0
  176. package/src/hooks/use-locale.jsx +6 -0
  177. package/src/index.js +43 -0
  178. package/src/locales/en.jsx +15 -0
  179. package/src/locales/index.jsx +13 -0
  180. package/src/locales/zh.jsx +15 -0
  181. package/src/types.d.ts +355 -0
  182. package/src/utils.js +395 -0
  183. package/vite.config.mjs +29 -0
package/lib/types.d.ts ADDED
@@ -0,0 +1,355 @@
1
+ import type { AxiosInstance } from 'axios';
2
+ import type { EventEmitter } from 'eventemitter3';
3
+ import { DEFAULT_TIMEOUT } from './constant';
4
+ import type { ReactNode } from 'react';
5
+
6
+ export type ConnectMessages = {
7
+ title: string;
8
+ scan: string;
9
+ success: ReactNode;
10
+ confirm?: string; // 貌似没有地方使用,先设置为非必填
11
+ error?: string;
12
+ };
13
+
14
+ // FIXME: @zhanghan 将来需要改成 ts,直接从常量值 LOGIN_PROVIDER 中提取类型,目前只能写成这样
15
+ export type WalletProvider = 'wallet' | 'auth0' | 'apple' | 'github' | 'google' | 'passkey';
16
+
17
+ export type WalletOS = 'web' | 'android' | 'ios' | '';
18
+ export type UserRole = 'guest' | 'member' | 'admin' | 'owner' | string;
19
+ export type BaseLocale = 'en' | 'zh';
20
+ export type UserLocale = BaseLocale | string;
21
+
22
+ export type ConnectProps = {
23
+ /**
24
+ * @example login
25
+ */
26
+ action: string;
27
+ containerEl?: Element;
28
+ /**
29
+ * @default "/api/did"
30
+ */
31
+ prefix?: string;
32
+ /**
33
+ * @default "en"
34
+ */
35
+ locale?: 'en' | 'zh';
36
+ /**
37
+ * @default false
38
+ */
39
+ popup?: boolean;
40
+ /**
41
+ * @default 2*1000
42
+ */
43
+ checkInterval?: number;
44
+ /**
45
+ * @default 5*60*1000
46
+ */
47
+ checkTimeout?: number;
48
+ /**
49
+ * @default 2*1000
50
+ */
51
+ closeTimeout?: number;
52
+ /**
53
+ * @default {}
54
+ */
55
+ extraParams?: object;
56
+ /**
57
+ * @default "_t_"
58
+ */
59
+ tokenKey?: string;
60
+ /**
61
+ * @default "_ek_"
62
+ */
63
+ encKey?: string;
64
+ /**
65
+ * @default "''"
66
+ */
67
+ baseUrl?: string;
68
+ /**
69
+ * @default {
70
+ title: 'DID Connect',
71
+ scan: 'Scan QR code to complete this action',
72
+ confirm: 'Confirm on your DID Wallet',
73
+ success: 'Success!'
74
+ }
75
+ */
76
+ messages?: ConnectMessages;
77
+ /**
78
+ * @default true
79
+ */
80
+ autoConnect?: boolean;
81
+ /**
82
+ * @default true
83
+ */
84
+ forceConnected?: boolean | string;
85
+ /**
86
+ * @default true
87
+ */
88
+ saveConnect?: boolean;
89
+ /**
90
+ * @default true
91
+ */
92
+ useSocket?: boolean;
93
+ /**
94
+ * @default true
95
+ */
96
+ allowWallet?: boolean;
97
+ /**
98
+ * @default true
99
+ */
100
+ passkeyBehavior?: 'none' | 'both' | 'only-existing' | 'only-new';
101
+ /**
102
+ * @default "wallet"
103
+ */
104
+ provider?: 'wallet' | 'auth0' | '';
105
+ /**
106
+ * @default 160
107
+ */
108
+ qrcodeSize?: number;
109
+ /**
110
+ * @default true
111
+ */
112
+ showDownload?: boolean;
113
+ /**
114
+ * @default "https://web.abtwallet.io"
115
+ */
116
+ webWalletUrl?: string;
117
+ /**
118
+ * @default ["web", "mobile", "github", "apple", "google", "auth0", "passkey"]
119
+ */
120
+ enabledConnectTypes?: Array<'web' | 'mobile' | 'auth0', 'github' | 'apple' | 'google' | 'passkey'>;
121
+ extraContent?: any;
122
+ loadingEle?: any;
123
+ /**
124
+ * @default false
125
+ */
126
+ disableSwitchApp?: boolean;
127
+ /**
128
+ * @default false
129
+ */
130
+ hideCloseButton?: boolean;
131
+ /**
132
+ * @default {}
133
+ */
134
+ options?: {
135
+ /**
136
+ * @default true
137
+ */
138
+ showQuickConnect?: boolean;
139
+ };
140
+ onRecreateSession?: Function;
141
+ checkFn?: () => boolean;
142
+ onSuccess?: (result: object) => void;
143
+ onError?: (error: any) => void;
144
+ onClose?: Function;
145
+ };
146
+
147
+ export type OpenConnect = (params: ConnectProps) => void;
148
+ export type OpenConnectPopup = (
149
+ params: ConnectProps,
150
+ options?: {
151
+ baseUrl?: string;
152
+ locale?: BaseLocale;
153
+ }
154
+ ) => void;
155
+
156
+ export type OpenDidConnect = (
157
+ params: ConnectProps,
158
+ options?: {
159
+ /**
160
+ * 打开 DID Connect 的模式
161
+ * @default 'popup'
162
+ */
163
+ openMode?: 'redirect' | 'window' | 'popup';
164
+ requirements?: {
165
+ /**
166
+ * 是否要求登录
167
+ * @default true
168
+ */
169
+ login?: boolean;
170
+ /**
171
+ * 是否要求绑定 DID Wallet 账户
172
+ * @default true
173
+ */
174
+ bindWallet?: boolean;
175
+ /**
176
+ * 是否要求绑定 DID Spaces
177
+ * @default false
178
+ */
179
+ bindDidSpaces?: false | 'read' | 'full';
180
+ // bindOAuth?: boolea // 暂不支持,这里要配置的情况会稍微复杂一些
181
+ };
182
+ baseUrl?: string;
183
+ locale?: BaseLocale;
184
+ }
185
+ ) => void;
186
+
187
+ export type CloseConnect = Function;
188
+
189
+ export type CommonSessionFn = (done?: Function, params?: object) => void;
190
+
191
+ export type LoginSessionFn = (
192
+ done?: Function,
193
+ params?: {
194
+ openMode: 'redirect' | 'window'; // iframe: 暂未启用
195
+ provider?: 'wallet';
196
+ redirect?: string;
197
+ forceConnected?: string;
198
+ sourceAppPid?: string;
199
+ passkeyBehavior?: string;
200
+ [key: string]: any;
201
+ },
202
+ origin?: string
203
+ ) => any;
204
+
205
+ export type LogoutSessionFn = (done?: Function) => void;
206
+
207
+ export type Passport = {
208
+ id: string;
209
+ name: string;
210
+ title: string;
211
+ role: UserRole;
212
+ };
213
+ export type ConnectAccount = {
214
+ provider: WalletProvider;
215
+ did: string;
216
+ pk: string;
217
+ id?: string;
218
+ firstLoginAt?: string;
219
+ lastLoginAt?: string;
220
+ lastLoginIp?: string;
221
+ };
222
+
223
+ export type SessionUser = {
224
+ avatar: string;
225
+ did: string;
226
+ email: string;
227
+ fullName: string;
228
+ remark?: string;
229
+ role?: UserRole;
230
+ sourceAppPid: null | string;
231
+ sourceProvider: WalletProvider;
232
+ };
233
+
234
+ export type UserSession = {
235
+ id: string;
236
+ appName: string;
237
+ appPid: string;
238
+ updatedAt: string;
239
+ userDid: string;
240
+ visitorId: string;
241
+ extra: object;
242
+ user: SessionUser;
243
+ passportId?: string;
244
+ };
245
+
246
+ export type User = {
247
+ approved: boolean;
248
+ avatar: string;
249
+ connectedAccounts: ConnectAccount[];
250
+ did: string;
251
+ pk: string;
252
+ email: string;
253
+ fullName: string;
254
+ role: UserRole;
255
+ locale: UserLocale;
256
+ passports: Passport[];
257
+ permissions: any[];
258
+ sourceAppPid?: string;
259
+ sourceProvider?: WalletProvider;
260
+ didSpace?: object;
261
+ remark?: string;
262
+ createdAt: string;
263
+ updatedAt: string;
264
+ firstLoginAt?: string;
265
+ lastLoginAt?: string;
266
+ lastLoginIp?: string;
267
+ };
268
+
269
+ export type SessionProps = {
270
+ action: string;
271
+ error: string;
272
+ initialized: boolean;
273
+ loading: boolean;
274
+ open: boolean;
275
+ walletOS: WalletOS;
276
+ user?: User;
277
+ locale: UserLocale;
278
+ provider?: WalletProvider;
279
+ baseUrl?: string;
280
+ federatedMaster?: object;
281
+ login: LoginSessionFn;
282
+ logout: LogoutSessionFn;
283
+ switch: Function;
284
+ switchDid: CommonSessionFn;
285
+ autoSwitchDid: Function;
286
+ switchProfile: CommonSessionFn;
287
+ switchPassport: CommonSessionFn;
288
+ bindWallet: CommonSessionFn;
289
+ refresh: Function;
290
+ updateConnectedInfo: (data: object) => void;
291
+ openDidConnect: OpenDidConnect;
292
+
293
+ useOAuth: Function;
294
+ OAuthProvider: Function;
295
+ OAuthConsumer: Function;
296
+ OAuthContext: object;
297
+
298
+ usePasskey: Function;
299
+ PasskeyProvider: Function;
300
+ PasskeyConsumer: Function;
301
+ PasskeyContext: object;
302
+
303
+ useDid: (options: { session: Session }) => void;
304
+ WrapDid: Function;
305
+ getUserSessions: () => Promise<UserSession[]>;
306
+ };
307
+
308
+ export type SessionStorageProps = {
309
+ getToken: Function;
310
+ setToken: Function;
311
+ removeToken: Function;
312
+ };
313
+
314
+ export type SessionContext = {
315
+ api: AxiosInstance; // api 实例(axios)
316
+ events: EventEmitter; // session 事件订阅器
317
+ storage: SessionStorageProps; // sessionToken 的存储实例
318
+ session: SessionProps; // session 实例
319
+ connectApi: {
320
+ open: OpenConnect;
321
+ close: CloseConnect;
322
+ }; // use-connect 的 connectApi
323
+ };
324
+
325
+ export interface TokenState {
326
+ checking: boolean;
327
+ loading: boolean;
328
+ token: string;
329
+ url: string;
330
+ store: object;
331
+ status: 'created' | 'scanned' | 'succeed' | 'error' | 'timeout' | 'busy' | 'forbidden';
332
+ error: string;
333
+ checkCount: number;
334
+ mfaCode?: number;
335
+ appInfo: object;
336
+ memberAppInfo: object;
337
+ connectedDid: string;
338
+ saveConnect: boolean;
339
+ inExistingSession: boolean;
340
+ nextWorkflow?: string;
341
+ baseUrl: string;
342
+ prefix: string;
343
+ extraParams: object;
344
+ checkFn: Function;
345
+ results: object;
346
+ action: string;
347
+ provider: 'wallet' | 'auth0' | 'apple' | 'github' | 'google';
348
+ }
349
+
350
+ export type SwitchBehavior = 'auto' | 'disabled' | 'required';
351
+ export type DIDConnectUrlOptions = {
352
+ switchBehavior: SwitchBehavior;
353
+ sourceAppPid: string;
354
+ forceConnected: boolean | string;
355
+ };
package/lib/utils.js ADDED
@@ -0,0 +1,214 @@
1
+ import { Buffer as a } from "buffer";
2
+ import g from "tweetnacl-sealedbox-js";
3
+ import { getCookieOptions as v, getVisitorId as A } from "@arcblock/ux/lib/Util";
4
+ import { getVisitorId as _e, setVisitorId as ke } from "@arcblock/ux/lib/Util";
5
+ import c from "js-cookie";
6
+ import l from "lodash/isNil";
7
+ import U from "lodash/isString";
8
+ import d from "lodash/isUndefined";
9
+ import { createAxios as E, BlockletSDK as P } from "@blocklet/js-sdk";
10
+ import { withQuery as T } from "ufo";
11
+ import { isValid as m, isFromPublicKey as L } from "@arcblock/did";
12
+ import { getSafeUrl as S } from "@arcblock/ux/lib/Util/security";
13
+ import { createDebug as x, createLogger as C } from "@arcblock/ux/lib/Util/logger";
14
+ import N from "./package.json.js";
15
+ import { DID_CONNECT_URL_PARAMS_NAME as w, DEFAULT_WINDOW_TIMEOUT as D } from "./constant.js";
16
+ import { NotOpenError as I } from "./error.js";
17
+ export * from "@arcblock/ux/lib/Util/wallet";
18
+ const { version: O } = N, Z = x("did-connect"), ee = C("did-connect");
19
+ function h(e) {
20
+ return (e + "===".slice((e.length + 3) % 4)).replace(/-/g, "+").replace(/_/g, "/");
21
+ }
22
+ function b(e) {
23
+ return e.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
24
+ }
25
+ const re = (e) => b(window.btoa(e)), oe = (e) => window.atob(h(e)), ne = (e) => {
26
+ const o = new URL(e), r = decodeURIComponent(o.searchParams.get("url"));
27
+ return new URL(r).searchParams.get("_t_");
28
+ }, W = (e, o) => {
29
+ let r = o?.publisher;
30
+ if (!r) {
31
+ if (e?.agentDid)
32
+ return e.agentDid;
33
+ r = e?.publisher;
34
+ }
35
+ return r ? r.replace("did:abt:", "") : globalThis.blocklet?.appPid || globalThis.blocklet?.appId || globalThis.env?.appId || "";
36
+ }, z = (e) => {
37
+ const o = {
38
+ connected_did: e.did || "",
39
+ connected_pk: e.pk || "",
40
+ connected_app: W(e.appInfo, e.memberAppInfo)
41
+ };
42
+ return e?.connectedWallet?.os && (o.connected_wallet_os = e.connectedWallet.os), o;
43
+ }, te = (e, o = !1) => {
44
+ if (!e) return;
45
+ o || (e = z(e));
46
+ const r = v({
47
+ expireInDays: 7,
48
+ returnDomain: !1
49
+ });
50
+ !l(e.connected_did) && !l(e.connected_pk) && m(e.connected_did) && L(e.connected_did, e.connected_pk) && (c.set("connected_did", e.connected_did, r), c.set("connected_pk", e.connected_pk, r)), !l(e.connected_app) && m(e.connected_app) && c.set("connected_app", e.connected_app, r), e.connected_wallet_os && c.set("connected_wallet_os", e.connected_wallet_os, r);
51
+ }, se = (e) => b(a.from(e).toString("base64")), u = (e) => Uint8Array.from(a.from(h(e), "base64")), ie = (e, o, r) => {
52
+ const n = g.open(
53
+ Uint8Array.from(a.from(e, "base64")),
54
+ u(o),
55
+ u(r)
56
+ );
57
+ return JSON.parse(a.from(n).toString("utf8"));
58
+ }, ae = (e, o) => a.from(g.seal(Uint8Array.from(a.from(e)), u(o))).toString("base64"), ce = (e, o = "_t_") => {
59
+ const r = new URL(e), n = {
60
+ baseUrl: r.origin,
61
+ prefix: r.pathname.replace(/\/auth$/, ""),
62
+ token: r.searchParams.get(o) || ""
63
+ };
64
+ if (!n.baseUrl)
65
+ throw new Error("Invalid next workflow: origin empty");
66
+ if (!n.token)
67
+ throw new Error("Invalid next workflow: token not found");
68
+ return n;
69
+ }, f = (e, o) => {
70
+ let r = e.message;
71
+ const { response: n } = e;
72
+ return n && (r = n.data?.error || n.data?.message || n.data || o, r = typeof r == "object" ? o : r), r;
73
+ }, pe = (e, o, r) => {
74
+ if (!e)
75
+ return e;
76
+ if (!e.name)
77
+ return f(e, o);
78
+ switch (e.name) {
79
+ case "NotAllowedError":
80
+ return r ? r("webauthn.error.canceled") : "Authentication was canceled";
81
+ case "SecurityError":
82
+ return r ? r("webauthn.error.security") : "A security error occurred during authentication";
83
+ case "NotSupportedError":
84
+ return r ? r("webauthn.error.notSupported") : "This browser does not support passkey authentication";
85
+ case "AbortError":
86
+ return r ? r("webauthn.error.aborted") : "Authentication was aborted";
87
+ default:
88
+ return console.warn("Unhandled WebAuthn error type:", e.name), f(e, o);
89
+ }
90
+ }, le = (e = {}, { lazy: o = !1, lazyTime: r = 300 } = {}) => {
91
+ const n = {
92
+ ...e.headers,
93
+ "x-did-connect-version": O
94
+ }, i = E(
95
+ {
96
+ ...e,
97
+ headers: n
98
+ },
99
+ { lazy: o, lazyTime: r }
100
+ );
101
+ return i.interceptors.request.use((t) => {
102
+ const s = A();
103
+ return s && (t.headers["x-blocklet-visitor-id"] = s), t;
104
+ }), i;
105
+ }, ue = (e = 0) => new Promise((o) => {
106
+ setTimeout(() => {
107
+ o();
108
+ }, e);
109
+ });
110
+ function de() {
111
+ if (typeof window > "u")
112
+ return null;
113
+ const e = window.navigator.languages && window.navigator.languages[0] || window.navigator.language || window.navigator.browserLanguage || window.navigator.userLanguage || window.navigator.systemLanguage || null;
114
+ return {
115
+ "zh-CN": "zh",
116
+ "zh-TW": "zh",
117
+ zh: "zh",
118
+ en: "en"
119
+ }[e] || "en";
120
+ }
121
+ function me(e, o) {
122
+ return [void 0, null, ""].includes(e) ? o : e / 86400;
123
+ }
124
+ async function we() {
125
+ const e = window.location.href;
126
+ try {
127
+ const o = new URL(e), r = o.searchParams.get(w);
128
+ if (r) {
129
+ o.searchParams.delete(w);
130
+ const n = JSON.parse(a.from(r, "base64").toString("utf-8"));
131
+ if (U(n.forceConnected) && d(n.sourceAppPid)) {
132
+ const t = await new P().user.getUserPublicInfo({ did: n.forceConnected });
133
+ d(t?.sourceAppPid) || (n.sourceAppPid = t.sourceAppPid);
134
+ }
135
+ return {
136
+ params: n,
137
+ url: o.href
138
+ };
139
+ }
140
+ } catch {
141
+ console.warn("Failed to decode did-connect url params");
142
+ }
143
+ return {
144
+ params: null,
145
+ url: e
146
+ };
147
+ }
148
+ const fe = (e, { width: o = 680, height: r = 720, name: n = "did-connect:popup", offsetX: i = 0, offsetY: t = 0 } = {}) => {
149
+ const s = S(e, { allowDomains: null }), _ = window.screenX + (window.innerWidth - o) / 2 + i, k = window.screenY + (window.innerHeight - r) / 2 + t, y = [
150
+ `left=${_}`,
151
+ `top=${k}`,
152
+ `width=${o}`,
153
+ `height=${r}`,
154
+ "resizable=no",
155
+ // not working
156
+ "scrollbars=yes",
157
+ "status=yes",
158
+ "popup=yes"
159
+ ], p = window.open("", n, y.join(","));
160
+ if (p === null)
161
+ throw new I();
162
+ return p.location.href = T(s, {
163
+ // NOTICE: 携带当前页面的 origin,用于在 popup 中通过该参数判断是否可以发送 postMessage,即使该参数被伪造,最终也只有该域名能接收到消息,所以没有关系
164
+ opener: window.location.origin
165
+ }), p;
166
+ }, ge = (e) => new Promise((o, r) => {
167
+ let n, i;
168
+ const t = ({ data: s }) => {
169
+ if (s && s.type === "authorization_response") {
170
+ if (s?.error) {
171
+ console.error(s.error);
172
+ return;
173
+ }
174
+ setTimeout(() => {
175
+ e.popup?.close(), clearTimeout(i), clearInterval(n), window.removeEventListener("message", t, !1), o(s);
176
+ }, e.closeTimeout || 0);
177
+ }
178
+ };
179
+ i = setTimeout(
180
+ () => {
181
+ clearInterval(n), r(new Error("Timeout")), window.removeEventListener("message", t, !1);
182
+ },
183
+ (e.timeoutInSeconds || D) * 1e3
184
+ ), n = setInterval(() => {
185
+ e.popup?.closed && (clearInterval(n), clearTimeout(i), window.removeEventListener("message", t, !1), r(new Error("Popup closed")));
186
+ }, 1e3), window.addEventListener("message", t);
187
+ });
188
+ export {
189
+ le as createAxios,
190
+ Z as debug,
191
+ oe as decodeConnectUrl,
192
+ u as decodeKey,
193
+ we as decodeUrlParams,
194
+ ie as decrypt,
195
+ re as encodeConnectUrl,
196
+ se as encodeKey,
197
+ ae as encrypt,
198
+ me as formatCacheTtl,
199
+ f as getApiErrorMessage,
200
+ W as getAppId,
201
+ de as getBrowserLang,
202
+ z as getConnectedInfo,
203
+ _e as getVisitorId,
204
+ pe as getWebAuthnErrorMessage,
205
+ ee as logger,
206
+ fe as openPopup,
207
+ ce as parseNextWorkflow,
208
+ ne as parseTokenFromConnectUrl,
209
+ ge as runPopup,
210
+ ke as setVisitorId,
211
+ ue as sleep,
212
+ te as updateConnectedInfo,
213
+ O as version
214
+ };
package/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "@arcblock/did-connect-react",
3
+ "version": "3.1.0",
4
+ "description": "Client side library to work with DID Connect by ArcBlock.",
5
+ "keywords": [
6
+ "react",
7
+ "arcblock",
8
+ "component"
9
+ ],
10
+ "author": "wangshijun<wangshijun2010@gmail.com>",
11
+ "homepage": "https://github.com/ArcBlock/ux#readme",
12
+ "license": "Apache-2.0",
13
+ "main": "lib/index.js",
14
+ "module": "lib/index.js",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/ArcBlock/ux.git"
18
+ },
19
+ "scripts": {
20
+ "lint": "eslint src tests --ext js --ext jsx",
21
+ "lint:fix": "npm run lint -- --fix",
22
+ "build": "vite build",
23
+ "autoexports": "node tools/auto-exports.js",
24
+ "watch": "vite build --watch",
25
+ "precommit": "CI=1 npm run lint",
26
+ "prepush": "CI=1 npm run lint",
27
+ "prepublish": "npm run build",
28
+ "test": "node tools/jest.js",
29
+ "coverage": "npm run test -- --coverage"
30
+ },
31
+ "bugs": {
32
+ "url": "https://github.com/ArcBlock/ux/issues"
33
+ },
34
+ "dependencies": {
35
+ "@arcblock/bridge": "3.1.0",
36
+ "@arcblock/did": "^1.21.2",
37
+ "@arcblock/icons": "3.1.0",
38
+ "@arcblock/react-hooks": "3.1.0",
39
+ "@arcblock/ws": "^1.21.2",
40
+ "@fontsource/lexend": "^5.2.9",
41
+ "@iconify-icons/logos": "^1.2.36",
42
+ "@iconify-icons/material-symbols": "^1.2.58",
43
+ "@iconify/react": "^5.2.1",
44
+ "@ocap/util": "^1.21.2",
45
+ "@simplewebauthn/browser": "^13.1.0",
46
+ "ahooks": "^3.8.5",
47
+ "axios": "^1.10.0",
48
+ "base64-url": "^2.3.3",
49
+ "buffer": "^6.0.3",
50
+ "color-convert": "^3.1.0",
51
+ "eventemitter3": "^5.0.1",
52
+ "flat": "^5.0.2",
53
+ "js-cookie": "^2.2.1",
54
+ "jwt-decode": "^3.1.2",
55
+ "lodash": "^4.17.21",
56
+ "mdi-material-ui": "^7.9.4",
57
+ "p-queue": "^6.6.2",
58
+ "p-retry": "^6.2.1",
59
+ "p-wait-for": "^5.0.2",
60
+ "path-to-regexp": "^1.9.0",
61
+ "semver": "^7.7.2",
62
+ "tweetnacl": "^1.0.3",
63
+ "tweetnacl-sealedbox-js": "^1.2.0",
64
+ "ufo": "^1.6.1"
65
+ },
66
+ "peerDependencies": {
67
+ "@arcblock/ux": "^3.0.23",
68
+ "@blocklet/js-sdk": "^1.16.46",
69
+ "@blocklet/theme": "^3.0.23",
70
+ "@emotion/react": "^11.14.0",
71
+ "@emotion/styled": "^11.14.0",
72
+ "@mui/material": "^7.2.0",
73
+ "react": "^19.0.0",
74
+ "react-dom": "^19.0.0"
75
+ },
76
+ "publishConfig": {
77
+ "access": "public"
78
+ },
79
+ "devDependencies": {
80
+ "eslint-plugin-react-hooks": "^4.6.2",
81
+ "jest": "^29.7.0"
82
+ },
83
+ "gitHead": "3d6b460689cc9015fc66567efc1b868874ceb18b"
84
+ }
@@ -0,0 +1,2 @@
1
+ // eslint-disable-next-line no-restricted-exports
2
+ export { default } from '@arcblock/ux/lib/Address';
@@ -0,0 +1,2 @@
1
+ // eslint-disable-next-line no-restricted-exports
2
+ export { default } from '@arcblock/ux/lib/Avatar';
@@ -0,0 +1,7 @@
1
+ export { default as Basic } from './demo/basic';
2
+ export { default as WithDifferentSizes } from './demo/with-different-sizes';
3
+ export { default as CustomText } from './demo/custom-text';
4
+
5
+ export default {
6
+ title: 'Deprecated/DID-Connect/Button',
7
+ };
@@ -0,0 +1,21 @@
1
+ /* eslint-disable react/require-default-props */
2
+ import PropTypes from 'prop-types';
3
+ import Button from '@arcblock/ux/lib/Button';
4
+ import ConnectLogo from '@arcblock/icons/lib/ConnectLogo';
5
+ import { Box } from '@mui/material';
6
+
7
+ /**
8
+ * ConnectButton
9
+ */
10
+ export default function ConnectButton({ children = null, ...rest }) {
11
+ return (
12
+ <Button color="did" variant="contained" {...rest}>
13
+ <Box sx={{ fontWeight: 400 }}>{children || 'Continue With'}</Box>
14
+ <ConnectLogo style={{ width: 'auto', height: '1.2em', margin: '0 4px 0 8px' }} />
15
+ </Button>
16
+ );
17
+ }
18
+
19
+ ConnectButton.propTypes = {
20
+ children: PropTypes.any,
21
+ };