@account-kit/signer 4.60.1 → 4.62.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/dist/esm/base.d.ts +59 -3
- package/dist/esm/base.js +77 -17
- package/dist/esm/base.js.map +1 -1
- package/dist/esm/client/base.d.ts +47 -23
- package/dist/esm/client/base.js +127 -110
- package/dist/esm/client/base.js.map +1 -1
- package/dist/esm/client/index.d.ts +18 -4
- package/dist/esm/client/index.js +83 -0
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/types.d.ts +36 -0
- package/dist/esm/client/types.js.map +1 -1
- package/dist/esm/session/manager.d.ts +3 -3
- package/dist/esm/signer.d.ts +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/types/base.d.ts +59 -3
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/client/base.d.ts +47 -23
- package/dist/types/client/base.d.ts.map +1 -1
- package/dist/types/client/index.d.ts +18 -4
- package/dist/types/client/index.d.ts.map +1 -1
- package/dist/types/client/types.d.ts +36 -0
- package/dist/types/client/types.d.ts.map +1 -1
- package/dist/types/session/manager.d.ts +3 -3
- package/dist/types/signer.d.ts +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +6 -6
- package/src/base.ts +111 -16
- package/src/client/base.ts +159 -138
- package/src/client/index.ts +122 -3
- package/src/client/types.ts +40 -0
- package/src/version.ts +1 -1
package/dist/esm/client/base.js
CHANGED
|
@@ -7,7 +7,6 @@ import { NotAuthenticatedError, OAuthProvidersError } from "../errors.js";
|
|
|
7
7
|
import { getDefaultProviderCustomization } from "../oauth.js";
|
|
8
8
|
import { base64UrlEncode } from "../utils/base64UrlEncode.js";
|
|
9
9
|
import { resolveRelativeUrl } from "../utils/resolveRelativeUrl.js";
|
|
10
|
-
import { assertNever } from "../utils/typeAssertions.js";
|
|
11
10
|
import { VERSION } from "../version.js";
|
|
12
11
|
import { secp256k1 } from "@noble/curves/secp256k1";
|
|
13
12
|
import { Point } from "@noble/secp256k1";
|
|
@@ -98,66 +97,140 @@ export class BaseSignerClient {
|
|
|
98
97
|
}
|
|
99
98
|
});
|
|
100
99
|
/**
|
|
101
|
-
*
|
|
102
|
-
* email.
|
|
103
|
-
*
|
|
104
|
-
* You must contact Alchemy to enable this feature for your team, as there are
|
|
105
|
-
* important security considerations. In particular, you must not call this
|
|
106
|
-
* without first validating that the user owns this email account.
|
|
100
|
+
* Removes the email for the authenticated user, disallowing them from login with that email.
|
|
107
101
|
*
|
|
108
|
-
* @
|
|
109
|
-
* @returns {Promise<void>} A promise that resolves when the email is set
|
|
102
|
+
* @returns {Promise<string>} A promise that resolves when the email is removed
|
|
110
103
|
* @throws {NotAuthenticatedError} If the user is not authenticated
|
|
111
104
|
*/
|
|
112
|
-
Object.defineProperty(this, "
|
|
105
|
+
Object.defineProperty(this, "removeEmail", {
|
|
113
106
|
enumerable: true,
|
|
114
107
|
configurable: true,
|
|
115
108
|
writable: true,
|
|
116
|
-
value: async (
|
|
117
|
-
|
|
118
|
-
|
|
109
|
+
value: async () => {
|
|
110
|
+
await this.updateEmail("");
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
Object.defineProperty(this, "updateEmail", {
|
|
114
|
+
enumerable: true,
|
|
115
|
+
configurable: true,
|
|
116
|
+
writable: true,
|
|
117
|
+
value: async (email, verificationToken) => {
|
|
118
|
+
if (!this.user) {
|
|
119
|
+
throw new NotAuthenticatedError();
|
|
119
120
|
}
|
|
120
|
-
|
|
121
|
+
// Unverified use is legacy & requires team flag.
|
|
122
|
+
const isUnverified = email && !verificationToken;
|
|
123
|
+
const stampedRequest = isUnverified
|
|
124
|
+
? await this.turnkeyClient.stampUpdateUser({
|
|
125
|
+
type: "ACTIVITY_TYPE_UPDATE_USER",
|
|
126
|
+
timestampMs: Date.now().toString(),
|
|
127
|
+
organizationId: this.user.orgId,
|
|
128
|
+
parameters: {
|
|
129
|
+
userId: this.user.userId,
|
|
130
|
+
userEmail: email,
|
|
131
|
+
},
|
|
132
|
+
})
|
|
133
|
+
: await this.turnkeyClient.stampUpdateUserEmail({
|
|
134
|
+
type: "ACTIVITY_TYPE_UPDATE_USER_EMAIL",
|
|
135
|
+
timestampMs: Date.now().toString(),
|
|
136
|
+
organizationId: this.user.orgId,
|
|
137
|
+
parameters: {
|
|
138
|
+
userId: this.user.userId,
|
|
139
|
+
userEmail: email,
|
|
140
|
+
verificationToken,
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
await this.request("/v1/update-email-auth", {
|
|
144
|
+
stampedRequest,
|
|
145
|
+
});
|
|
146
|
+
this.user = {
|
|
147
|
+
...this.user,
|
|
148
|
+
email: email || undefined,
|
|
149
|
+
};
|
|
121
150
|
}
|
|
122
151
|
});
|
|
123
152
|
/**
|
|
124
|
-
*
|
|
153
|
+
* Updates the phone number for the authenticated user, allowing them to login with that
|
|
154
|
+
* phone number. Must be called after calling `initOtp` with the phone number.
|
|
125
155
|
*
|
|
126
|
-
* @
|
|
156
|
+
* @param {VerificationOtp} otp The OTP object including the OTP ID and OTP code
|
|
157
|
+
* @returns {Promise<void>} A promise that resolves when the phone number is set
|
|
127
158
|
* @throws {NotAuthenticatedError} If the user is not authenticated
|
|
128
159
|
*/
|
|
129
|
-
Object.defineProperty(this, "
|
|
160
|
+
Object.defineProperty(this, "setPhoneNumber", {
|
|
161
|
+
enumerable: true,
|
|
162
|
+
configurable: true,
|
|
163
|
+
writable: true,
|
|
164
|
+
value: async (otp) => {
|
|
165
|
+
const { verificationToken } = await this.request("/v1/verify-otp", {
|
|
166
|
+
otpId: otp.id,
|
|
167
|
+
otpCode: otp.code,
|
|
168
|
+
});
|
|
169
|
+
const { contact } = jwtDecode(verificationToken);
|
|
170
|
+
await this.updatePhoneNumber(contact, verificationToken);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
/**
|
|
174
|
+
* Removes the phone number for the authenticated user, disallowing them from login with that phone number.
|
|
175
|
+
*
|
|
176
|
+
* @returns {Promise<void>} A promise that resolves when the phone number is removed
|
|
177
|
+
* @throws {NotAuthenticatedError} If the user is not authenticated
|
|
178
|
+
*/
|
|
179
|
+
Object.defineProperty(this, "removePhoneNumber", {
|
|
130
180
|
enumerable: true,
|
|
131
181
|
configurable: true,
|
|
132
182
|
writable: true,
|
|
133
183
|
value: async () => {
|
|
134
|
-
|
|
135
|
-
// support clearing the email once set, so we set it to a known
|
|
136
|
-
// inaccessible address instead.
|
|
137
|
-
await this.updateEmail("not.enabled@example.invalid");
|
|
184
|
+
await this.updatePhoneNumber("");
|
|
138
185
|
}
|
|
139
186
|
});
|
|
140
|
-
Object.defineProperty(this, "
|
|
187
|
+
Object.defineProperty(this, "updatePhoneNumber", {
|
|
141
188
|
enumerable: true,
|
|
142
189
|
configurable: true,
|
|
143
190
|
writable: true,
|
|
144
|
-
value: async (
|
|
191
|
+
value: async (phone, verificationToken) => {
|
|
145
192
|
if (!this.user) {
|
|
146
193
|
throw new NotAuthenticatedError();
|
|
147
194
|
}
|
|
148
|
-
|
|
149
|
-
|
|
195
|
+
if (phone.trim() && !verificationToken) {
|
|
196
|
+
throw new Error("Verification token is required to change phone number.");
|
|
197
|
+
}
|
|
198
|
+
const stampedRequest = await this.turnkeyClient.stampUpdateUserPhoneNumber({
|
|
199
|
+
type: "ACTIVITY_TYPE_UPDATE_USER_PHONE_NUMBER",
|
|
150
200
|
timestampMs: Date.now().toString(),
|
|
151
201
|
organizationId: this.user.orgId,
|
|
152
202
|
parameters: {
|
|
153
203
|
userId: this.user.userId,
|
|
154
|
-
|
|
155
|
-
|
|
204
|
+
userPhoneNumber: phone,
|
|
205
|
+
verificationToken,
|
|
156
206
|
},
|
|
157
207
|
});
|
|
158
|
-
await this.request("/v1/update-
|
|
208
|
+
await this.request("/v1/update-phone-auth", {
|
|
159
209
|
stampedRequest,
|
|
160
210
|
});
|
|
211
|
+
this.user = {
|
|
212
|
+
...this.user,
|
|
213
|
+
phone: phone || undefined,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
/**
|
|
218
|
+
* Initiates an OTP (One-Time Password) verification process for a user contact.
|
|
219
|
+
*
|
|
220
|
+
* @param {("email" | "sms")} type - The type of OTP to send, either "email" or "sms"
|
|
221
|
+
* @param {string} contact - The email address or phone number to send the OTP to
|
|
222
|
+
* @returns {Promise<{ otpId: string }>} A promise that resolves to an object containing the OTP ID
|
|
223
|
+
* @throws {NotAuthenticatedError} When no user is currently authenticated
|
|
224
|
+
*/
|
|
225
|
+
Object.defineProperty(this, "initOtp", {
|
|
226
|
+
enumerable: true,
|
|
227
|
+
configurable: true,
|
|
228
|
+
writable: true,
|
|
229
|
+
value: async (type, contact) => {
|
|
230
|
+
return await this.request("/v1/init-otp", {
|
|
231
|
+
otpType: type === "email" ? "OTP_TYPE_EMAIL" : "OTP_TYPE_SMS",
|
|
232
|
+
contact,
|
|
233
|
+
});
|
|
161
234
|
}
|
|
162
235
|
});
|
|
163
236
|
/**
|
|
@@ -587,7 +660,7 @@ export class BaseSignerClient {
|
|
|
587
660
|
};
|
|
588
661
|
return {
|
|
589
662
|
stampHeaderName: "X-Stamp",
|
|
590
|
-
stampHeaderValue: base64UrlEncode(Buffer.from(JSON.stringify(stamp))),
|
|
663
|
+
stampHeaderValue: base64UrlEncode(Buffer.from(JSON.stringify(stamp)).buffer),
|
|
591
664
|
};
|
|
592
665
|
},
|
|
593
666
|
})
|
|
@@ -923,67 +996,6 @@ export class BaseSignerClient {
|
|
|
923
996
|
});
|
|
924
997
|
// #endregion
|
|
925
998
|
// #region PRIVATE METHODS
|
|
926
|
-
Object.defineProperty(this, "exportAsSeedPhrase", {
|
|
927
|
-
enumerable: true,
|
|
928
|
-
configurable: true,
|
|
929
|
-
writable: true,
|
|
930
|
-
value: async (stamper) => {
|
|
931
|
-
if (!this.user) {
|
|
932
|
-
throw new NotAuthenticatedError();
|
|
933
|
-
}
|
|
934
|
-
const { wallets } = await this.turnkeyClient.getWallets({
|
|
935
|
-
organizationId: this.user.orgId,
|
|
936
|
-
});
|
|
937
|
-
const walletAccounts = await Promise.all(wallets.map(({ walletId }) => this.turnkeyClient.getWalletAccounts({
|
|
938
|
-
organizationId: this.user.orgId,
|
|
939
|
-
walletId,
|
|
940
|
-
}))).then((x) => x.flatMap((x) => x.accounts));
|
|
941
|
-
const walletAccount = walletAccounts.find((x) => x.address === this.user.address);
|
|
942
|
-
if (!walletAccount) {
|
|
943
|
-
throw new Error(`Could not find wallet associated with ${this.user.address}`);
|
|
944
|
-
}
|
|
945
|
-
const { activity } = await this.turnkeyClient.exportWallet({
|
|
946
|
-
organizationId: this.user.orgId,
|
|
947
|
-
type: "ACTIVITY_TYPE_EXPORT_WALLET",
|
|
948
|
-
timestampMs: Date.now().toString(),
|
|
949
|
-
parameters: {
|
|
950
|
-
walletId: walletAccount.walletId,
|
|
951
|
-
targetPublicKey: stamper.publicKey(),
|
|
952
|
-
},
|
|
953
|
-
});
|
|
954
|
-
const { exportBundle } = await this.pollActivityCompletion(activity, this.user.orgId, "exportWalletResult");
|
|
955
|
-
const result = await stamper.injectWalletExportBundle(exportBundle, this.user.orgId);
|
|
956
|
-
if (!result) {
|
|
957
|
-
throw new Error("Failed to inject wallet export bundle");
|
|
958
|
-
}
|
|
959
|
-
return result;
|
|
960
|
-
}
|
|
961
|
-
});
|
|
962
|
-
Object.defineProperty(this, "exportAsPrivateKey", {
|
|
963
|
-
enumerable: true,
|
|
964
|
-
configurable: true,
|
|
965
|
-
writable: true,
|
|
966
|
-
value: async (stamper) => {
|
|
967
|
-
if (!this.user) {
|
|
968
|
-
throw new NotAuthenticatedError();
|
|
969
|
-
}
|
|
970
|
-
const { activity } = await this.turnkeyClient.exportWalletAccount({
|
|
971
|
-
organizationId: this.user.orgId,
|
|
972
|
-
type: "ACTIVITY_TYPE_EXPORT_WALLET_ACCOUNT",
|
|
973
|
-
timestampMs: Date.now().toString(),
|
|
974
|
-
parameters: {
|
|
975
|
-
address: this.user.address,
|
|
976
|
-
targetPublicKey: stamper.publicKey(),
|
|
977
|
-
},
|
|
978
|
-
});
|
|
979
|
-
const { exportBundle } = await this.pollActivityCompletion(activity, this.user.orgId, "exportWalletAccountResult");
|
|
980
|
-
const result = await stamper.injectKeyExportBundle(exportBundle, this.user.orgId);
|
|
981
|
-
if (!result) {
|
|
982
|
-
throw new Error("Failed to inject wallet export bundle");
|
|
983
|
-
}
|
|
984
|
-
return result;
|
|
985
|
-
}
|
|
986
|
-
});
|
|
987
999
|
/**
|
|
988
1000
|
* Returns the authentication url for the selected OAuth Proivder
|
|
989
1001
|
*
|
|
@@ -1061,7 +1073,7 @@ export class BaseSignerClient {
|
|
|
1061
1073
|
openerOrigin: mode === "popup" ? window.location.origin : undefined,
|
|
1062
1074
|
fetchIdTokenOnly: oauthParams.fetchIdTokenOnly,
|
|
1063
1075
|
};
|
|
1064
|
-
const state = base64UrlEncode(new TextEncoder().encode(JSON.stringify(stateObject)));
|
|
1076
|
+
const state = base64UrlEncode(new TextEncoder().encode(JSON.stringify(stateObject)).buffer);
|
|
1065
1077
|
const authUrl = new URL(authEndpoint);
|
|
1066
1078
|
const params = {
|
|
1067
1079
|
redirect_uri: oauthCallbackUrl,
|
|
@@ -1172,25 +1184,6 @@ export class BaseSignerClient {
|
|
|
1172
1184
|
setStamper(stamper) {
|
|
1173
1185
|
this.turnkeyClient.stamper = stamper;
|
|
1174
1186
|
}
|
|
1175
|
-
/**
|
|
1176
|
-
* Exports wallet credentials based on the specified type, either as a SEED_PHRASE or PRIVATE_KEY.
|
|
1177
|
-
*
|
|
1178
|
-
* @param {object} params The parameters for exporting the wallet
|
|
1179
|
-
* @param {ExportWalletStamper} params.exportStamper The stamper used for exporting the wallet
|
|
1180
|
-
* @param {"SEED_PHRASE" | "PRIVATE_KEY"} params.exportAs Specifies the format for exporting the wallet, either as a SEED_PHRASE or PRIVATE_KEY
|
|
1181
|
-
* @returns {Promise<boolean>} A promise that resolves to true if the export is successful
|
|
1182
|
-
*/
|
|
1183
|
-
exportWalletInner(params) {
|
|
1184
|
-
const { exportAs } = params;
|
|
1185
|
-
switch (exportAs) {
|
|
1186
|
-
case "PRIVATE_KEY":
|
|
1187
|
-
return this.exportAsPrivateKey(params.exportStamper);
|
|
1188
|
-
case "SEED_PHRASE":
|
|
1189
|
-
return this.exportAsSeedPhrase(params.exportStamper);
|
|
1190
|
-
default:
|
|
1191
|
-
assertNever(exportAs, `Unknown export mode: ${exportAs}`);
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
1187
|
/**
|
|
1195
1188
|
* Authenticates the user by either email or passkey account creation flow. Emits events during the process.
|
|
1196
1189
|
*
|
|
@@ -1244,5 +1237,29 @@ export class BaseSignerClient {
|
|
|
1244
1237
|
this.eventEmitter.emit("connectedPasskey", this.user);
|
|
1245
1238
|
return result;
|
|
1246
1239
|
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Implementation for setEmail method with optional OTP verification.
|
|
1242
|
+
*
|
|
1243
|
+
* @param {string | VerificationOtp} params An OTP object containing the OTP ID & OTP code (or an email address for legacy usage)
|
|
1244
|
+
* @returns {Promise<void>} A promise that resolves to the updated email address
|
|
1245
|
+
*/
|
|
1246
|
+
async setEmail(params) {
|
|
1247
|
+
if (typeof params === "string") {
|
|
1248
|
+
// Legacy use, requires team flag.
|
|
1249
|
+
const contact = params;
|
|
1250
|
+
if (!contact) {
|
|
1251
|
+
throw new Error("Email must not be empty. Use removeEmail() to remove email auth.");
|
|
1252
|
+
}
|
|
1253
|
+
await this.updateEmail(contact);
|
|
1254
|
+
return contact;
|
|
1255
|
+
}
|
|
1256
|
+
const { verificationToken } = await this.request("/v1/verify-otp", {
|
|
1257
|
+
otpId: params.id,
|
|
1258
|
+
otpCode: params.code,
|
|
1259
|
+
});
|
|
1260
|
+
const { contact } = jwtDecode(verificationToken);
|
|
1261
|
+
await this.updateEmail(contact, verificationToken);
|
|
1262
|
+
return contact;
|
|
1263
|
+
}
|
|
1247
1264
|
}
|
|
1248
1265
|
//# sourceMappingURL=base.js.map
|