@account-kit/react-native-signer 4.9.0 → 4.11.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 (65) hide show
  1. package/lib/commonjs/client.js +68 -12
  2. package/lib/commonjs/client.js.map +1 -1
  3. package/lib/commonjs/errors.js +15 -0
  4. package/lib/commonjs/errors.js.map +1 -0
  5. package/lib/commonjs/index.js.map +1 -1
  6. package/lib/commonjs/signer.js +27 -3
  7. package/lib/commonjs/signer.js.map +1 -1
  8. package/lib/commonjs/utils/base64UrlEncode.js +12 -0
  9. package/lib/commonjs/utils/base64UrlEncode.js.map +1 -0
  10. package/lib/commonjs/utils/buffer-polyfill.js +7 -0
  11. package/lib/commonjs/utils/buffer-polyfill.js.map +1 -0
  12. package/lib/commonjs/utils/parseUrlParams.js +19 -0
  13. package/lib/commonjs/utils/parseUrlParams.js.map +1 -0
  14. package/lib/module/client.js +72 -14
  15. package/lib/module/client.js.map +1 -1
  16. package/lib/module/errors.js +10 -0
  17. package/lib/module/errors.js.map +1 -0
  18. package/lib/module/index.js +0 -1
  19. package/lib/module/index.js.map +1 -1
  20. package/lib/module/signer.js +26 -3
  21. package/lib/module/signer.js.map +1 -1
  22. package/lib/module/utils/base64UrlEncode.js +7 -0
  23. package/lib/module/utils/base64UrlEncode.js.map +1 -0
  24. package/lib/module/utils/buffer-polyfill.js +7 -0
  25. package/lib/module/utils/buffer-polyfill.js.map +1 -0
  26. package/lib/module/utils/parseUrlParams.js +14 -0
  27. package/lib/module/utils/parseUrlParams.js.map +1 -0
  28. package/lib/typescript/commonjs/src/client.d.ts +10 -4
  29. package/lib/typescript/commonjs/src/client.d.ts.map +1 -1
  30. package/lib/typescript/commonjs/src/errors.d.ts +6 -0
  31. package/lib/typescript/commonjs/src/errors.d.ts.map +1 -0
  32. package/lib/typescript/commonjs/src/index.d.ts +2 -1
  33. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  34. package/lib/typescript/commonjs/src/signer.d.ts +39 -3
  35. package/lib/typescript/commonjs/src/signer.d.ts.map +1 -1
  36. package/lib/typescript/commonjs/src/utils/base64UrlEncode.d.ts +2 -0
  37. package/lib/typescript/commonjs/src/utils/base64UrlEncode.d.ts.map +1 -0
  38. package/lib/typescript/commonjs/src/utils/buffer-polyfill.d.ts +2 -0
  39. package/lib/typescript/commonjs/src/utils/buffer-polyfill.d.ts.map +1 -0
  40. package/lib/typescript/commonjs/src/utils/parseUrlParams.d.ts +2 -0
  41. package/lib/typescript/commonjs/src/utils/parseUrlParams.d.ts.map +1 -0
  42. package/lib/typescript/module/src/client.d.ts +10 -4
  43. package/lib/typescript/module/src/client.d.ts.map +1 -1
  44. package/lib/typescript/module/src/errors.d.ts +6 -0
  45. package/lib/typescript/module/src/errors.d.ts.map +1 -0
  46. package/lib/typescript/module/src/index.d.ts +2 -1
  47. package/lib/typescript/module/src/index.d.ts.map +1 -1
  48. package/lib/typescript/module/src/signer.d.ts +39 -3
  49. package/lib/typescript/module/src/signer.d.ts.map +1 -1
  50. package/lib/typescript/module/src/utils/base64UrlEncode.d.ts +2 -0
  51. package/lib/typescript/module/src/utils/base64UrlEncode.d.ts.map +1 -0
  52. package/lib/typescript/module/src/utils/buffer-polyfill.d.ts +2 -0
  53. package/lib/typescript/module/src/utils/buffer-polyfill.d.ts.map +1 -0
  54. package/lib/typescript/module/src/utils/parseUrlParams.d.ts +2 -0
  55. package/lib/typescript/module/src/utils/parseUrlParams.d.ts.map +1 -0
  56. package/package.json +10 -9
  57. package/react-native.config.js +11 -0
  58. package/src/client.ts +94 -17
  59. package/src/errors.ts +10 -0
  60. package/src/index.ts +2 -0
  61. package/src/signer.ts +30 -5
  62. package/src/utils/base64UrlEncode.ts +11 -0
  63. package/src/utils/buffer-polyfill.ts +5 -0
  64. package/src/utils/parseUrlParams.ts +14 -0
  65. package/src/index.tsx +0 -2
package/src/client.ts CHANGED
@@ -1,8 +1,11 @@
1
+ import "./utils/buffer-polyfill.js";
2
+ import "./utils/mmkv-localstorage-polyfill.js";
3
+
1
4
  /* eslint-disable import/extensions */
2
- import "./utils/mmkv-localstorage-polyfill";
3
5
  import { type ConnectionConfig } from "@aa-sdk/core";
4
6
  import {
5
7
  BaseSignerClient,
8
+ OauthFailedError,
6
9
  type AlchemySignerClientEvents,
7
10
  type AuthenticatingEventMetadata,
8
11
  type CreateAccountParams,
@@ -14,12 +17,19 @@ import {
14
17
  type SignupResponse,
15
18
  type User,
16
19
  } from "@account-kit/signer";
17
- import NativeTEKStamper from "./NativeTEKStamper";
20
+ import { InAppBrowser } from "react-native-inappbrowser-reborn";
18
21
  import { z } from "zod";
22
+ import { InAppBrowserUnavailableError } from "./errors";
23
+ import NativeTEKStamper from "./NativeTEKStamper.js";
24
+ import { parseSearchParams } from "./utils/parseUrlParams";
19
25
 
20
26
  export const RNSignerClientParamsSchema = z.object({
21
27
  connection: z.custom<ConnectionConfig>(),
22
28
  rootOrgId: z.string().optional(),
29
+ oauthCallbackUrl: z
30
+ .string()
31
+ .optional()
32
+ .default("https://signer.alchemy.com/callback"),
23
33
  });
24
34
 
25
35
  export type RNSignerClientParams = z.input<typeof RNSignerClientParamsSchema>;
@@ -27,14 +37,24 @@ export type RNSignerClientParams = z.input<typeof RNSignerClientParamsSchema>;
27
37
  // TODO: need to emit events
28
38
  export class RNSignerClient extends BaseSignerClient<undefined> {
29
39
  private stamper = NativeTEKStamper;
40
+ oauthCallbackUrl: string;
41
+ private validAuthenticatingTypes: AuthenticatingEventMetadata["type"][] = [
42
+ "email",
43
+ "otp",
44
+ "oauth",
45
+ ];
46
+
30
47
  constructor(params: RNSignerClientParams) {
31
- const { connection, rootOrgId } = RNSignerClientParamsSchema.parse(params);
48
+ const { connection, rootOrgId, oauthCallbackUrl } =
49
+ RNSignerClientParamsSchema.parse(params);
32
50
 
33
51
  super({
34
52
  stamper: NativeTEKStamper,
35
53
  rootOrgId: rootOrgId ?? "24c1acf5-810f-41e0-a503-d5d13fa8e830",
36
54
  connection,
37
55
  });
56
+
57
+ this.oauthCallbackUrl = oauthCallbackUrl;
38
58
  }
39
59
 
40
60
  override async submitOtpCode(
@@ -95,14 +115,14 @@ export class RNSignerClient extends BaseSignerClient<undefined> {
95
115
  authenticatingType: AuthenticatingEventMetadata["type"];
96
116
  idToken?: string;
97
117
  }): Promise<User> {
98
- if (
99
- params.authenticatingType !== "email" &&
100
- params.authenticatingType !== "otp"
101
- ) {
118
+ if (!this.validAuthenticatingTypes.includes(params.authenticatingType)) {
102
119
  throw new Error("Unsupported authenticating type");
103
120
  }
104
121
 
105
- this.eventEmitter.emit("authenticating", { type: "email" });
122
+ this.eventEmitter.emit("authenticating", {
123
+ type: params.authenticatingType,
124
+ });
125
+
106
126
  await this.stamper.init();
107
127
 
108
128
  const result = await this.stamper.injectCredentialBundle(params.bundle);
@@ -116,15 +136,67 @@ export class RNSignerClient extends BaseSignerClient<undefined> {
116
136
  this.eventEmitter.emit(params.connectedEventName, user, params.bundle);
117
137
  return user;
118
138
  }
119
- override oauthWithRedirect(
120
- _args: Extract<OauthParams, { mode: "redirect" }>
121
- ): Promise<never> {
122
- throw new Error("Method not implemented.");
123
- }
139
+ override oauthWithRedirect = async (
140
+ args: Extract<OauthParams, { mode: "redirect" }>
141
+ ): Promise<User> => {
142
+ // Ensure the In-App Browser required for authentication is available
143
+ if (!(await InAppBrowser.isAvailable())) {
144
+ throw new InAppBrowserUnavailableError();
145
+ }
146
+
147
+ this.eventEmitter.emit("authenticating", { type: "oauth" });
148
+
149
+ const oauthParams = args;
150
+ const turnkeyPublicKey = await this.stamper.init();
151
+ const oauthCallbackUrl = this.oauthCallbackUrl;
152
+ const oauthConfig = await this.getOauthConfig();
153
+ const providerUrl = await this.getOauthProviderUrl({
154
+ oauthParams,
155
+ turnkeyPublicKey,
156
+ oauthCallbackUrl,
157
+ oauthConfig,
158
+ usesRelativeUrl: false,
159
+ });
160
+ const redirectUrl = args.redirectUrl;
161
+ const res = await InAppBrowser.openAuth(providerUrl, redirectUrl);
162
+
163
+ if (res.type !== "success" || !res.url) {
164
+ throw new OauthFailedError("An error occured completing your request");
165
+ }
166
+
167
+ const authResult = parseSearchParams(res.url);
168
+ const bundle = authResult["alchemy-bundle"] ?? "";
169
+ const orgId = authResult["alchemy-org-id"] ?? "";
170
+ const idToken = authResult["alchemy-id-token"] ?? "";
171
+ const isSignup = authResult["alchemy-is-signup"];
172
+ const error = authResult["alchemy-error"];
173
+
174
+ if (bundle && orgId && idToken) {
175
+ const user = await this.completeAuthWithBundle({
176
+ bundle,
177
+ orgId,
178
+ connectedEventName: "connectedOauth",
179
+ idToken,
180
+ authenticatingType: "oauth",
181
+ });
182
+
183
+ if (isSignup) {
184
+ this.eventEmitter.emit("newUserSignup");
185
+ }
186
+
187
+ return user;
188
+ }
189
+
190
+ // Throw the Alchemy error if available, otherwise throw a generic error.
191
+ throw new OauthFailedError(
192
+ error ?? "An error occured completing your request"
193
+ );
194
+ };
195
+
124
196
  override oauthWithPopup(
125
197
  _args: Extract<OauthParams, { mode: "popup" }>
126
198
  ): Promise<User> {
127
- throw new Error("Method not implemented.");
199
+ throw new Error("Method not implemented");
128
200
  }
129
201
 
130
202
  override async disconnect(): Promise<void> {
@@ -138,13 +210,18 @@ export class RNSignerClient extends BaseSignerClient<undefined> {
138
210
  override lookupUserWithPasskey(_user?: User): Promise<User> {
139
211
  throw new Error("Method not implemented.");
140
212
  }
141
- protected override getOauthConfig(): Promise<OauthConfig> {
142
- throw new Error("Method not implemented.");
143
- }
213
+
144
214
  protected override getWebAuthnAttestation(
145
215
  _options: CredentialCreationOptions,
146
216
  _userDetails?: { username: string }
147
217
  ): Promise<GetWebAuthnAttestationResult> {
148
218
  throw new Error("Method not implemented.");
149
219
  }
220
+
221
+ protected override getOauthConfig = async (): Promise<OauthConfig> => {
222
+ const publicKey = await this.stamper.init();
223
+
224
+ const nonce = this.getOauthNonce(publicKey);
225
+ return this.request("/v1/prepare-oauth", { nonce });
226
+ };
150
227
  }
package/src/errors.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { BaseError } from "@aa-sdk/core";
2
+
3
+ export class InAppBrowserUnavailableError extends BaseError {
4
+ override name = "InAppBrowserUnavailableError";
5
+ constructor() {
6
+ super(
7
+ "In-App Browser is not available. Please authenticate with a different method."
8
+ );
9
+ }
10
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export type * from "./signer.js";
2
+ export { RNAlchemySigner } from "./signer.js";
package/src/signer.ts CHANGED
@@ -1,10 +1,9 @@
1
- import { z } from "zod";
2
1
  import {
3
2
  BaseAlchemySigner,
4
3
  SessionManagerParamsSchema,
5
4
  } from "@account-kit/signer";
6
- // eslint-disable-next-line import/extensions
7
- import { RNSignerClient, RNSignerClientParamsSchema } from "./client";
5
+ import { z } from "zod";
6
+ import { RNSignerClient, RNSignerClientParamsSchema } from "./client.js";
8
7
 
9
8
  const RNAlchemySignerParamsSchema = z
10
9
  .object({
@@ -19,8 +18,8 @@ const RNAlchemySignerParamsSchema = z
19
18
 
20
19
  export type RNAlchemySignerParams = z.input<typeof RNAlchemySignerParamsSchema>;
21
20
 
22
- class RNAlchemySignerSingleton extends BaseAlchemySigner<RNSignerClient> {
23
- private static instance: BaseAlchemySigner<RNSignerClient>;
21
+ export class RNAlchemySignerSingleton extends BaseAlchemySigner<RNSignerClient> {
22
+ private static instance: RNAlchemySignerSingleton;
24
23
 
25
24
  private constructor(params: RNAlchemySignerParams) {
26
25
  if (!!RNAlchemySignerSingleton.instance) {
@@ -37,6 +36,7 @@ class RNAlchemySignerSingleton extends BaseAlchemySigner<RNSignerClient> {
37
36
  } else {
38
37
  client = params_.client;
39
38
  }
39
+
40
40
  super({
41
41
  client,
42
42
  sessionConfig,
@@ -51,8 +51,33 @@ class RNAlchemySignerSingleton extends BaseAlchemySigner<RNSignerClient> {
51
51
  }
52
52
  }
53
53
 
54
+ /**
55
+ * Factory function to create or retrieve a singleton instance of RNAlchemySigner.
56
+ *
57
+ * @example
58
+ * ```ts twoslash
59
+ * import { RNAlchemySigner } from "@account-kit/react-native-signer";
60
+ *
61
+ * const signer = RNAlchemySigner({
62
+ * client: {
63
+ * connection: {
64
+ * apiKey: "YOUR_API_KEY"
65
+ * },
66
+ * },
67
+ * // optional config to override default session manager configs
68
+ * sessionConfig: {
69
+ * expirationTimeMs: 1000 * 60 * 60 // 60 minutes
70
+ * }
71
+ * });
72
+ * ```
73
+ *
74
+ * @param {RNAlchemySignerParams} params The parameters required to configure the RNAlchemySigner instance.
75
+ * @returns {RNAlchemySignerSingleton} The singleton instance of RNAlchemySigner configured with the provided parameters.
76
+ */
54
77
  export function RNAlchemySigner(params: RNAlchemySignerParams) {
55
78
  const instance = RNAlchemySignerSingleton.getInstance(params);
56
79
 
57
80
  return instance;
58
81
  }
82
+
83
+ export type RNAlchemySignerType = RNAlchemySignerSingleton;
@@ -0,0 +1,11 @@
1
+ import { Buffer } from "buffer";
2
+
3
+ export const base64UrlEncode = (
4
+ challenge: ArrayBuffer | ArrayBufferLike
5
+ ): string => {
6
+ return Buffer.from(challenge)
7
+ .toString("base64")
8
+ .replace(/\+/g, "-")
9
+ .replace(/\//g, "_")
10
+ .replace(/=/g, "");
11
+ };
@@ -0,0 +1,5 @@
1
+ import { Buffer } from "buffer";
2
+
3
+ if (!global.Buffer) {
4
+ global.Buffer = Buffer;
5
+ }
@@ -0,0 +1,14 @@
1
+ export const parseSearchParams = (url: string) => {
2
+ const regex = /[?&]([^=#]+)=([^&#]*)/g;
3
+
4
+ let params: Record<string, string> = {};
5
+ let match: RegExpExecArray | null;
6
+
7
+ while ((match = regex.exec(url))) {
8
+ if (match[1] !== undefined && match[2] !== undefined) {
9
+ params[match[1]] = match[2];
10
+ }
11
+ }
12
+
13
+ return params;
14
+ };
package/src/index.tsx DELETED
@@ -1,2 +0,0 @@
1
- // eslint-disable-next-line import/extensions
2
- export { RNAlchemySigner } from "./signer";