@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.
- package/lib/commonjs/client.js +68 -12
- package/lib/commonjs/client.js.map +1 -1
- package/lib/commonjs/errors.js +15 -0
- package/lib/commonjs/errors.js.map +1 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/signer.js +27 -3
- package/lib/commonjs/signer.js.map +1 -1
- package/lib/commonjs/utils/base64UrlEncode.js +12 -0
- package/lib/commonjs/utils/base64UrlEncode.js.map +1 -0
- package/lib/commonjs/utils/buffer-polyfill.js +7 -0
- package/lib/commonjs/utils/buffer-polyfill.js.map +1 -0
- package/lib/commonjs/utils/parseUrlParams.js +19 -0
- package/lib/commonjs/utils/parseUrlParams.js.map +1 -0
- package/lib/module/client.js +72 -14
- package/lib/module/client.js.map +1 -1
- package/lib/module/errors.js +10 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/index.js +0 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/signer.js +26 -3
- package/lib/module/signer.js.map +1 -1
- package/lib/module/utils/base64UrlEncode.js +7 -0
- package/lib/module/utils/base64UrlEncode.js.map +1 -0
- package/lib/module/utils/buffer-polyfill.js +7 -0
- package/lib/module/utils/buffer-polyfill.js.map +1 -0
- package/lib/module/utils/parseUrlParams.js +14 -0
- package/lib/module/utils/parseUrlParams.js.map +1 -0
- package/lib/typescript/commonjs/src/client.d.ts +10 -4
- package/lib/typescript/commonjs/src/client.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/errors.d.ts +6 -0
- package/lib/typescript/commonjs/src/errors.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +2 -1
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/signer.d.ts +39 -3
- package/lib/typescript/commonjs/src/signer.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/utils/base64UrlEncode.d.ts +2 -0
- package/lib/typescript/commonjs/src/utils/base64UrlEncode.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/utils/buffer-polyfill.d.ts +2 -0
- package/lib/typescript/commonjs/src/utils/buffer-polyfill.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/utils/parseUrlParams.d.ts +2 -0
- package/lib/typescript/commonjs/src/utils/parseUrlParams.d.ts.map +1 -0
- package/lib/typescript/module/src/client.d.ts +10 -4
- package/lib/typescript/module/src/client.d.ts.map +1 -1
- package/lib/typescript/module/src/errors.d.ts +6 -0
- package/lib/typescript/module/src/errors.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +2 -1
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/signer.d.ts +39 -3
- package/lib/typescript/module/src/signer.d.ts.map +1 -1
- package/lib/typescript/module/src/utils/base64UrlEncode.d.ts +2 -0
- package/lib/typescript/module/src/utils/base64UrlEncode.d.ts.map +1 -0
- package/lib/typescript/module/src/utils/buffer-polyfill.d.ts +2 -0
- package/lib/typescript/module/src/utils/buffer-polyfill.d.ts.map +1 -0
- package/lib/typescript/module/src/utils/parseUrlParams.d.ts +2 -0
- package/lib/typescript/module/src/utils/parseUrlParams.d.ts.map +1 -0
- package/package.json +10 -9
- package/react-native.config.js +11 -0
- package/src/client.ts +94 -17
- package/src/errors.ts +10 -0
- package/src/index.ts +2 -0
- package/src/signer.ts +30 -5
- package/src/utils/base64UrlEncode.ts +11 -0
- package/src/utils/buffer-polyfill.ts +5 -0
- package/src/utils/parseUrlParams.ts +14 -0
- 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
|
|
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 } =
|
|
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", {
|
|
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
|
-
|
|
121
|
-
): Promise<
|
|
122
|
-
|
|
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
|
-
|
|
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
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
|
-
|
|
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:
|
|
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,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