@account-kit/signer 4.35.0 → 4.36.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 +2 -2
- package/dist/esm/base.js +22 -5
- package/dist/esm/base.js.map +1 -1
- package/dist/esm/client/base.d.ts +4 -292
- package/dist/esm/client/base.js.map +1 -1
- package/dist/esm/client/index.d.ts +14 -26
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/types.js.map +1 -1
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/metrics.js.map +1 -1
- package/dist/esm/oauth.js.map +1 -1
- package/dist/esm/session/manager.d.ts +2 -2
- package/dist/esm/session/manager.js.map +1 -1
- package/dist/esm/signer.d.ts +25 -117
- package/dist/esm/signer.js.map +1 -1
- package/dist/esm/solanaSigner.js.map +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 +2 -2
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/client/base.d.ts +4 -292
- package/dist/types/client/base.d.ts.map +1 -1
- package/dist/types/client/index.d.ts +14 -26
- package/dist/types/client/index.d.ts.map +1 -1
- package/dist/types/session/manager.d.ts +2 -2
- package/dist/types/session/manager.d.ts.map +1 -1
- package/dist/types/signer.d.ts +25 -117
- package/dist/types/signer.d.ts.map +1 -1
- package/dist/types/utils/base64UrlEncode.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +6 -8
- package/src/base.ts +75 -54
- package/src/client/base.ts +37 -38
- package/src/client/index.ts +10 -10
- package/src/client/types.ts +1 -1
- package/src/errors.ts +1 -1
- package/src/metrics.ts +1 -1
- package/src/oauth.ts +1 -1
- package/src/session/manager.ts +15 -12
- package/src/signer.ts +1 -1
- package/src/solanaSigner.ts +15 -15
- package/src/version.ts +1 -1
package/src/base.ts
CHANGED
|
@@ -141,8 +141,8 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
141
141
|
mfaRequired: false,
|
|
142
142
|
mfaFactorId: undefined,
|
|
143
143
|
},
|
|
144
|
-
} satisfies AlchemySignerStore
|
|
145
|
-
)
|
|
144
|
+
}) satisfies AlchemySignerStore,
|
|
145
|
+
),
|
|
146
146
|
);
|
|
147
147
|
// NOTE: it's important that the session manager share a client
|
|
148
148
|
// with the signer. The SessionManager leverages the Signer's client
|
|
@@ -170,7 +170,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
170
170
|
*/
|
|
171
171
|
on = <E extends AlchemySignerEvent>(
|
|
172
172
|
event: E,
|
|
173
|
-
listener: AlchemySignerEvents[E]
|
|
173
|
+
listener: AlchemySignerEvents[E],
|
|
174
174
|
) => {
|
|
175
175
|
// NOTE: we're using zustand here to handle this because we are able to use the fireImmediately
|
|
176
176
|
// option which deals with a possible race condition where the listener is added after the event
|
|
@@ -183,8 +183,8 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
183
183
|
(status) =>
|
|
184
184
|
status === AlchemySignerStatus.CONNECTED &&
|
|
185
185
|
(listener as AlchemySignerEvents["connected"])(
|
|
186
|
-
this.store.getState().user
|
|
187
|
-
)
|
|
186
|
+
this.store.getState().user!,
|
|
187
|
+
),
|
|
188
188
|
);
|
|
189
189
|
case "disconnected":
|
|
190
190
|
return subscribeWithDelayedFireImmediately(
|
|
@@ -192,13 +192,13 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
192
192
|
({ status }) => status,
|
|
193
193
|
(status) =>
|
|
194
194
|
status === AlchemySignerStatus.DISCONNECTED &&
|
|
195
|
-
(listener as AlchemySignerEvents["disconnected"])()
|
|
195
|
+
(listener as AlchemySignerEvents["disconnected"])(),
|
|
196
196
|
);
|
|
197
197
|
case "statusChanged":
|
|
198
198
|
return subscribeWithDelayedFireImmediately(
|
|
199
199
|
this.store,
|
|
200
200
|
({ status }) => status,
|
|
201
|
-
listener as AlchemySignerEvents["statusChanged"]
|
|
201
|
+
listener as AlchemySignerEvents["statusChanged"],
|
|
202
202
|
);
|
|
203
203
|
case "errorChanged":
|
|
204
204
|
return subscribeWithDelayedFireImmediately(
|
|
@@ -206,8 +206,8 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
206
206
|
({ error }) => error,
|
|
207
207
|
(error) =>
|
|
208
208
|
(listener as AlchemySignerEvents["errorChanged"])(
|
|
209
|
-
error ?? undefined
|
|
210
|
-
)
|
|
209
|
+
error ?? undefined,
|
|
210
|
+
),
|
|
211
211
|
);
|
|
212
212
|
case "newUserSignup":
|
|
213
213
|
return subscribeWithDelayedFireImmediately(
|
|
@@ -215,14 +215,14 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
215
215
|
({ isNewUser }) => isNewUser,
|
|
216
216
|
(isNewUser) => {
|
|
217
217
|
if (isNewUser) (listener as AlchemySignerEvents["newUserSignup"])();
|
|
218
|
-
}
|
|
218
|
+
},
|
|
219
219
|
);
|
|
220
220
|
case "mfaStatusChanged":
|
|
221
221
|
return subscribeWithDelayedFireImmediately(
|
|
222
222
|
this.store,
|
|
223
223
|
({ mfaStatus }) => mfaStatus,
|
|
224
224
|
(mfaStatus) =>
|
|
225
|
-
(listener as AlchemySignerEvents["mfaStatusChanged"])(mfaStatus)
|
|
225
|
+
(listener as AlchemySignerEvents["mfaStatusChanged"])(mfaStatus),
|
|
226
226
|
);
|
|
227
227
|
case "emailAuthLinkingRequired":
|
|
228
228
|
return subscribeWithDelayedFireImmediately(
|
|
@@ -231,10 +231,10 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
231
231
|
(authLinkingStatus) => {
|
|
232
232
|
if (authLinkingStatus) {
|
|
233
233
|
(listener as AlchemySignerEvents["emailAuthLinkingRequired"])(
|
|
234
|
-
authLinkingStatus.email
|
|
234
|
+
authLinkingStatus.email,
|
|
235
235
|
);
|
|
236
236
|
}
|
|
237
|
-
}
|
|
237
|
+
},
|
|
238
238
|
);
|
|
239
239
|
default:
|
|
240
240
|
assertNever(event, `Unknown event type ${event}`);
|
|
@@ -337,7 +337,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
337
337
|
});
|
|
338
338
|
throw error;
|
|
339
339
|
});
|
|
340
|
-
}
|
|
340
|
+
},
|
|
341
341
|
);
|
|
342
342
|
|
|
343
343
|
private trackAuthenticateType = (params: AuthParams) => {
|
|
@@ -458,7 +458,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
458
458
|
const { address } = await this.inner.whoami();
|
|
459
459
|
|
|
460
460
|
return address;
|
|
461
|
-
}
|
|
461
|
+
},
|
|
462
462
|
);
|
|
463
463
|
|
|
464
464
|
/**
|
|
@@ -529,16 +529,16 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
529
529
|
*/
|
|
530
530
|
signTypedData: <
|
|
531
531
|
const TTypedData extends TypedData | Record<string, unknown>,
|
|
532
|
-
TPrimaryType extends keyof TTypedData | "EIP712Domain" = keyof TTypedData
|
|
532
|
+
TPrimaryType extends keyof TTypedData | "EIP712Domain" = keyof TTypedData,
|
|
533
533
|
>(
|
|
534
|
-
params: TypedDataDefinition<TTypedData, TPrimaryType
|
|
534
|
+
params: TypedDataDefinition<TTypedData, TPrimaryType>,
|
|
535
535
|
) => Promise<Hex> = SignerLogger.profiled(
|
|
536
536
|
"BaseAlchemySigner.signTypedData",
|
|
537
537
|
async (params) => {
|
|
538
538
|
const messageHash = hashTypedData(params);
|
|
539
539
|
|
|
540
540
|
return this.inner.signRawMessage(messageHash);
|
|
541
|
-
}
|
|
541
|
+
},
|
|
542
542
|
);
|
|
543
543
|
|
|
544
544
|
/**
|
|
@@ -572,15 +572,16 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
572
572
|
* @returns {Promise<string>} a promise that resolves to the serialized transaction with the signature
|
|
573
573
|
*/
|
|
574
574
|
signTransaction: <
|
|
575
|
-
serializer extends
|
|
576
|
-
|
|
575
|
+
serializer extends
|
|
576
|
+
SerializeTransactionFn<TransactionSerializable> = SerializeTransactionFn<TransactionSerializable>,
|
|
577
|
+
transaction extends Parameters<serializer>[0] = Parameters<serializer>[0],
|
|
577
578
|
>(
|
|
578
579
|
transaction: transaction,
|
|
579
580
|
options?:
|
|
580
581
|
| {
|
|
581
582
|
serializer?: serializer | undefined;
|
|
582
583
|
}
|
|
583
|
-
| undefined
|
|
584
|
+
| undefined,
|
|
584
585
|
) => Promise<
|
|
585
586
|
IsNarrowable<
|
|
586
587
|
TransactionSerialized<GetTransactionType<transaction>>,
|
|
@@ -594,13 +595,13 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
594
595
|
const serializeFn = args?.serializer ?? serializeTransaction;
|
|
595
596
|
const serializedTx = serializeFn(tx);
|
|
596
597
|
const signatureHex = await this.inner.signRawMessage(
|
|
597
|
-
keccak256(serializedTx)
|
|
598
|
+
keccak256(serializedTx),
|
|
598
599
|
);
|
|
599
600
|
|
|
600
601
|
const signature = this.unpackSignRawMessageBytes(signatureHex);
|
|
601
602
|
|
|
602
603
|
return serializeFn(tx, signature);
|
|
603
|
-
}
|
|
604
|
+
},
|
|
604
605
|
);
|
|
605
606
|
|
|
606
607
|
/**
|
|
@@ -632,14 +633,13 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
632
633
|
* @returns {Promise<SignedAuthorization<number>> | undefined} a promise that resolves to the authorization with the signature
|
|
633
634
|
*/
|
|
634
635
|
signAuthorization: (
|
|
635
|
-
unsignedAuthorization: AuthorizationRequest<number
|
|
636
|
+
unsignedAuthorization: AuthorizationRequest<number>,
|
|
636
637
|
) => Promise<SignedAuthorization<number>> = SignerLogger.profiled(
|
|
637
638
|
"BaseAlchemySigner.signAuthorization",
|
|
638
639
|
async (unsignedAuthorization) => {
|
|
639
640
|
const hashedAuthorization = hashAuthorization(unsignedAuthorization);
|
|
640
|
-
const signedAuthorizationHex =
|
|
641
|
-
hashedAuthorization
|
|
642
|
-
);
|
|
641
|
+
const signedAuthorizationHex =
|
|
642
|
+
await this.inner.signRawMessage(hashedAuthorization);
|
|
643
643
|
const signature = this.unpackSignRawMessageBytes(signedAuthorizationHex);
|
|
644
644
|
const { address, contractAddress, ...unsignedAuthorizationRest } =
|
|
645
645
|
unsignedAuthorization;
|
|
@@ -649,7 +649,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
649
649
|
...signature,
|
|
650
650
|
address: address ?? contractAddress,
|
|
651
651
|
};
|
|
652
|
-
}
|
|
652
|
+
},
|
|
653
653
|
);
|
|
654
654
|
|
|
655
655
|
/**
|
|
@@ -686,7 +686,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
686
686
|
};
|
|
687
687
|
|
|
688
688
|
private unpackSignRawMessageBytes = (
|
|
689
|
-
hex: `0x${string}
|
|
689
|
+
hex: `0x${string}`,
|
|
690
690
|
): UnpackedSignature => {
|
|
691
691
|
return {
|
|
692
692
|
r: takeBytes(hex, { count: 32 }),
|
|
@@ -794,7 +794,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
794
794
|
* @returns {boolean} true if the wallet was exported successfully
|
|
795
795
|
*/
|
|
796
796
|
exportWallet: (
|
|
797
|
-
params: Parameters<(typeof this.inner)["exportWallet"]>[0]
|
|
797
|
+
params: Parameters<(typeof this.inner)["exportWallet"]>[0],
|
|
798
798
|
) => Promise<boolean> = async (params) => {
|
|
799
799
|
return this.inner.exportWallet(params);
|
|
800
800
|
};
|
|
@@ -836,9 +836,9 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
836
836
|
signMessage: (msg) => this.signMessage(msg.message),
|
|
837
837
|
signTypedData: <
|
|
838
838
|
const typedData extends TypedData | Record<string, unknown>,
|
|
839
|
-
primaryType extends keyof typedData | "EIP712Domain" = keyof typedData
|
|
839
|
+
primaryType extends keyof typedData | "EIP712Domain" = keyof typedData,
|
|
840
840
|
>(
|
|
841
|
-
typedDataDefinition: TypedDataDefinition<typedData, primaryType
|
|
841
|
+
typedDataDefinition: TypedDataDefinition<typedData, primaryType>,
|
|
842
842
|
) => this.signTypedData<typedData, primaryType>(typedDataDefinition),
|
|
843
843
|
signTransaction: this.signTransaction,
|
|
844
844
|
});
|
|
@@ -877,7 +877,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
877
877
|
};
|
|
878
878
|
|
|
879
879
|
private authenticateWithEmail = async (
|
|
880
|
-
params: Extract<AuthParams, { type: "email" }
|
|
880
|
+
params: Extract<AuthParams, { type: "email" }>,
|
|
881
881
|
): Promise<User> => {
|
|
882
882
|
if ("bundle" in params) {
|
|
883
883
|
return this.completeEmailAuth(params);
|
|
@@ -887,7 +887,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
887
887
|
params.email,
|
|
888
888
|
params.emailMode,
|
|
889
889
|
params.multiFactors,
|
|
890
|
-
params.redirectParams
|
|
890
|
+
params.redirectParams,
|
|
891
891
|
);
|
|
892
892
|
|
|
893
893
|
this.setAwaitingEmailAuth({ orgId, otpId, isNewUser });
|
|
@@ -906,7 +906,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
906
906
|
};
|
|
907
907
|
|
|
908
908
|
private authenticateWithPasskey = async (
|
|
909
|
-
args: Extract<AuthParams, { type: "passkey" }
|
|
909
|
+
args: Extract<AuthParams, { type: "passkey" }>,
|
|
910
910
|
): Promise<User> => {
|
|
911
911
|
let user: User;
|
|
912
912
|
const shouldCreateNew = async () => {
|
|
@@ -923,7 +923,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
923
923
|
args as Extract<
|
|
924
924
|
AuthParams,
|
|
925
925
|
{ type: "passkey" } & ({ email: string } | { createNew: true })
|
|
926
|
-
|
|
926
|
+
>,
|
|
927
927
|
);
|
|
928
928
|
// account creation for passkeys returns the whoami response so we don't have to
|
|
929
929
|
// call it again after signup
|
|
@@ -946,7 +946,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
946
946
|
};
|
|
947
947
|
|
|
948
948
|
private authenticateWithOauth = async (
|
|
949
|
-
args: Extract<AuthParams, { type: "oauth" }
|
|
949
|
+
args: Extract<AuthParams, { type: "oauth" }>,
|
|
950
950
|
): Promise<User> => {
|
|
951
951
|
this.store.setState({ authLinkingStatus: undefined });
|
|
952
952
|
const params: OauthParams = {
|
|
@@ -965,7 +965,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
965
965
|
};
|
|
966
966
|
|
|
967
967
|
private authenticateWithOtp = async (
|
|
968
|
-
args: Extract<AuthParams, { type: "otp" }
|
|
968
|
+
args: Extract<AuthParams, { type: "otp" }>,
|
|
969
969
|
): Promise<User> => {
|
|
970
970
|
const tempSession = this.sessionManager.getTemporarySession();
|
|
971
971
|
const { orgId, isNewUser } = tempSession ?? {};
|
|
@@ -1059,7 +1059,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
1059
1059
|
|
|
1060
1060
|
private handleMfaRequired(
|
|
1061
1061
|
encryptedPayload: string,
|
|
1062
|
-
multiFactors: MfaFactor[]
|
|
1062
|
+
multiFactors: MfaFactor[],
|
|
1063
1063
|
) {
|
|
1064
1064
|
// Store complete MFA context in the temporary session
|
|
1065
1065
|
const tempSession = this.sessionManager.getTemporarySession();
|
|
@@ -1154,7 +1154,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
1154
1154
|
email: string,
|
|
1155
1155
|
emailMode?: EmailType,
|
|
1156
1156
|
multiFactors?: VerifyMfaParams[],
|
|
1157
|
-
redirectParams?: URLSearchParams
|
|
1157
|
+
redirectParams?: URLSearchParams,
|
|
1158
1158
|
): Promise<{
|
|
1159
1159
|
orgId: string;
|
|
1160
1160
|
otpId?: string;
|
|
@@ -1193,7 +1193,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
1193
1193
|
}
|
|
1194
1194
|
|
|
1195
1195
|
private async completeEmailAuth(
|
|
1196
|
-
params: Extract<AuthParams, { type: "email"; bundle: string }
|
|
1196
|
+
params: Extract<AuthParams, { type: "email"; bundle: string }>,
|
|
1197
1197
|
): Promise<User> {
|
|
1198
1198
|
const temporarySession = params.orgId
|
|
1199
1199
|
? { orgId: params.orgId }
|
|
@@ -1307,12 +1307,12 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
1307
1307
|
* @returns {Promise<{ multiFactors: MfaFactor[] }>} A promise that resolves to the updated list of MFA factors
|
|
1308
1308
|
*/
|
|
1309
1309
|
verifyMfa: (
|
|
1310
|
-
params: VerifyMfaParams
|
|
1310
|
+
params: VerifyMfaParams,
|
|
1311
1311
|
) => Promise<{ multiFactors: MfaFactor[] }> = SignerLogger.profiled(
|
|
1312
1312
|
"BaseAlchemySigner.verifyMfa",
|
|
1313
1313
|
async (params) => {
|
|
1314
1314
|
return this.inner.verifyMfa(params);
|
|
1315
|
-
}
|
|
1315
|
+
},
|
|
1316
1316
|
);
|
|
1317
1317
|
|
|
1318
1318
|
/**
|
|
@@ -1343,12 +1343,12 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
1343
1343
|
* @returns {Promise<{ multiFactors: MfaFactor[] }>} A promise that resolves to the updated list of MFA factors
|
|
1344
1344
|
*/
|
|
1345
1345
|
removeMfa: (
|
|
1346
|
-
params: RemoveMfaParams
|
|
1346
|
+
params: RemoveMfaParams,
|
|
1347
1347
|
) => Promise<{ multiFactors: MfaFactor[] }> = SignerLogger.profiled(
|
|
1348
1348
|
"BaseAlchemySigner.removeMfa",
|
|
1349
1349
|
async (params) => {
|
|
1350
1350
|
return this.inner.removeMfa(params);
|
|
1351
|
-
}
|
|
1351
|
+
},
|
|
1352
1352
|
);
|
|
1353
1353
|
|
|
1354
1354
|
/**
|
|
@@ -1383,7 +1383,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
1383
1383
|
* @returns {Promise<User>} A promise that resolves to the authenticated user
|
|
1384
1384
|
*/
|
|
1385
1385
|
public async validateMultiFactors(
|
|
1386
|
-
params: ValidateMultiFactorsArgs
|
|
1386
|
+
params: ValidateMultiFactorsArgs,
|
|
1387
1387
|
): Promise<User> {
|
|
1388
1388
|
// Get MFA context from temporary session
|
|
1389
1389
|
const tempSession = this.sessionManager.getTemporarySession();
|
|
@@ -1393,7 +1393,7 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
1393
1393
|
!tempSession.mfaFactorId
|
|
1394
1394
|
) {
|
|
1395
1395
|
throw new Error(
|
|
1396
|
-
"No pending MFA context found. Call submitOtpCode() first."
|
|
1396
|
+
"No pending MFA context found. Call submitOtpCode() first.",
|
|
1397
1397
|
);
|
|
1398
1398
|
}
|
|
1399
1399
|
|
|
@@ -1518,22 +1518,43 @@ function toErrorInfo(error: unknown): ErrorInfo {
|
|
|
1518
1518
|
function subscribeWithDelayedFireImmediately<T>(
|
|
1519
1519
|
store: InternalStore,
|
|
1520
1520
|
selector: (state: AlchemySignerStore) => T,
|
|
1521
|
-
listener: (selectedState: T, previousSelectedState: T) => void
|
|
1521
|
+
listener: (selectedState: T, previousSelectedState: T) => void,
|
|
1522
1522
|
): () => void {
|
|
1523
|
-
|
|
1523
|
+
// Until this function has returned, maintain a queue of events that will be
|
|
1524
|
+
// processed once it does.
|
|
1525
|
+
const queue: [selectedState: T, previousSelectedState: T][] = [];
|
|
1526
|
+
let queueHasEmptied = false;
|
|
1527
|
+
let hasUnsubscribed = false;
|
|
1528
|
+
|
|
1529
|
+
function drainQueue() {
|
|
1530
|
+
// Note that this handles the case where more events are added to the queue
|
|
1531
|
+
// during the handling of previous events.
|
|
1532
|
+
for (let i = 0; i < queue.length && !hasUnsubscribed; i++) {
|
|
1533
|
+
const args = queue[i];
|
|
1534
|
+
listener(...args);
|
|
1535
|
+
}
|
|
1536
|
+
queueHasEmptied = true;
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
// Schedule the queue to be drained after this function has returned.
|
|
1540
|
+
setTimeout(drainQueue, 0);
|
|
1541
|
+
|
|
1524
1542
|
const unsubscribe = store.subscribe(
|
|
1525
1543
|
selector,
|
|
1526
1544
|
(...args) => {
|
|
1527
|
-
if (
|
|
1545
|
+
if (queueHasEmptied) {
|
|
1528
1546
|
listener(...args);
|
|
1529
1547
|
} else {
|
|
1530
|
-
|
|
1548
|
+
queue.push(args);
|
|
1531
1549
|
}
|
|
1532
1550
|
},
|
|
1533
|
-
{ fireImmediately: true }
|
|
1551
|
+
{ fireImmediately: true },
|
|
1534
1552
|
);
|
|
1535
|
-
|
|
1536
|
-
return
|
|
1553
|
+
|
|
1554
|
+
return () => {
|
|
1555
|
+
hasUnsubscribed = true;
|
|
1556
|
+
unsubscribe();
|
|
1557
|
+
};
|
|
1537
1558
|
}
|
|
1538
1559
|
|
|
1539
1560
|
function isAuthLinkingPrompt(result: unknown): result is AuthLinkingPrompt {
|
package/src/client/base.ts
CHANGED
|
@@ -82,7 +82,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
82
82
|
this.connectionConfig = ConnectionConfigSchema.parse(connection);
|
|
83
83
|
this.turnkeyClient = new TurnkeyClient(
|
|
84
84
|
{ baseUrl: "https://api.turnkey.com" },
|
|
85
|
-
stamper
|
|
85
|
+
stamper,
|
|
86
86
|
);
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -145,11 +145,11 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
145
145
|
// #region ABSTRACT METHODS
|
|
146
146
|
|
|
147
147
|
public abstract createAccount(
|
|
148
|
-
params: CreateAccountParams
|
|
148
|
+
params: CreateAccountParams,
|
|
149
149
|
): Promise<SignupResponse>;
|
|
150
150
|
|
|
151
151
|
public abstract initEmailAuth(
|
|
152
|
-
params: Omit<EmailAuthParams, "targetPublicKey"
|
|
152
|
+
params: Omit<EmailAuthParams, "targetPublicKey">,
|
|
153
153
|
): Promise<{ orgId: string; otpId?: string; multiFactors?: MfaFactor[] }>;
|
|
154
154
|
|
|
155
155
|
public abstract completeAuthWithBundle(params: {
|
|
@@ -161,15 +161,15 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
161
161
|
}): Promise<User>;
|
|
162
162
|
|
|
163
163
|
public abstract oauthWithRedirect(
|
|
164
|
-
args: Extract<OauthParams, { mode: "redirect" }
|
|
164
|
+
args: Extract<OauthParams, { mode: "redirect" }>,
|
|
165
165
|
): Promise<User>;
|
|
166
166
|
|
|
167
167
|
public abstract oauthWithPopup(
|
|
168
|
-
args: Extract<OauthParams, { mode: "popup" }
|
|
168
|
+
args: Extract<OauthParams, { mode: "popup" }>,
|
|
169
169
|
): Promise<User | AuthLinkingPrompt>;
|
|
170
170
|
|
|
171
171
|
public abstract submitOtpCode(
|
|
172
|
-
args: Omit<OtpParams, "targetPublicKey"
|
|
172
|
+
args: Omit<OtpParams, "targetPublicKey">,
|
|
173
173
|
): Promise<SubmitOtpCodeResponse>;
|
|
174
174
|
|
|
175
175
|
public abstract disconnect(): Promise<void>;
|
|
@@ -184,7 +184,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
184
184
|
|
|
185
185
|
protected abstract getWebAuthnAttestation(
|
|
186
186
|
options: CredentialCreationOptions,
|
|
187
|
-
userDetails?: { username: string }
|
|
187
|
+
userDetails?: { username: string },
|
|
188
188
|
): Promise<GetWebAuthnAttestationResult>;
|
|
189
189
|
|
|
190
190
|
// #endregion
|
|
@@ -200,7 +200,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
200
200
|
*/
|
|
201
201
|
public on = <E extends AlchemySignerClientEvent>(
|
|
202
202
|
event: E,
|
|
203
|
-
listener: AlchemySignerClientEvents[E]
|
|
203
|
+
listener: AlchemySignerClientEvents[E],
|
|
204
204
|
) => {
|
|
205
205
|
this.eventEmitter.on(event, listener as any);
|
|
206
206
|
|
|
@@ -218,9 +218,8 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
218
218
|
if (!this.user) {
|
|
219
219
|
throw new NotAuthenticatedError();
|
|
220
220
|
}
|
|
221
|
-
const { attestation, challenge } =
|
|
222
|
-
options
|
|
223
|
-
);
|
|
221
|
+
const { attestation, challenge } =
|
|
222
|
+
await this.getWebAuthnAttestation(options);
|
|
224
223
|
|
|
225
224
|
const { activity } = await this.turnkeyClient.createAuthenticators({
|
|
226
225
|
type: "ACTIVITY_TYPE_CREATE_AUTHENTICATORS_V2",
|
|
@@ -241,7 +240,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
241
240
|
const { authenticatorIds } = await this.pollActivityCompletion(
|
|
242
241
|
activity,
|
|
243
242
|
this.user.orgId,
|
|
244
|
-
"createAuthenticatorsResult"
|
|
243
|
+
"createAuthenticatorsResult",
|
|
245
244
|
);
|
|
246
245
|
|
|
247
246
|
return authenticatorIds;
|
|
@@ -263,7 +262,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
263
262
|
});
|
|
264
263
|
return {
|
|
265
264
|
isPasskeyAdded: resp.authenticators.some((it) =>
|
|
266
|
-
it.authenticatorName.startsWith("passkey-")
|
|
265
|
+
it.authenticatorName.startsWith("passkey-"),
|
|
267
266
|
),
|
|
268
267
|
};
|
|
269
268
|
};
|
|
@@ -276,7 +275,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
276
275
|
* @returns {Promise<void>} A Promise that resolves when the OAuth provider is added.
|
|
277
276
|
*/
|
|
278
277
|
public addOauthProvider = async (
|
|
279
|
-
params: AddOauthProviderParams
|
|
278
|
+
params: AddOauthProviderParams,
|
|
280
279
|
): Promise<void> => {
|
|
281
280
|
if (!this.user) {
|
|
282
281
|
throw new NotAuthenticatedError();
|
|
@@ -304,7 +303,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
304
303
|
*/
|
|
305
304
|
public whoami = async (
|
|
306
305
|
orgId = this.user?.orgId,
|
|
307
|
-
idToken?: string
|
|
306
|
+
idToken?: string,
|
|
308
307
|
): Promise<User> => {
|
|
309
308
|
if (this.user) {
|
|
310
309
|
return this.user;
|
|
@@ -376,7 +375,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
376
375
|
public stampGetOrganization = async (): Promise<TSignedRequest> => {
|
|
377
376
|
if (!this.user) {
|
|
378
377
|
throw new Error(
|
|
379
|
-
"User must be authenticated to stamp a get organization request"
|
|
378
|
+
"User must be authenticated to stamp a get organization request",
|
|
380
379
|
);
|
|
381
380
|
}
|
|
382
381
|
|
|
@@ -396,7 +395,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
396
395
|
* @throws {Error} If there is no authenticated user or the API key creation fails.
|
|
397
396
|
*/
|
|
398
397
|
public experimental_createApiKey = async (
|
|
399
|
-
params: experimental_CreateApiKeyParams
|
|
398
|
+
params: experimental_CreateApiKeyParams,
|
|
400
399
|
): Promise<void> => {
|
|
401
400
|
if (!this.user) {
|
|
402
401
|
throw new Error("User must be authenticated to create api key");
|
|
@@ -443,7 +442,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
443
442
|
*/
|
|
444
443
|
public signRawMessage = async (
|
|
445
444
|
msg: Hex,
|
|
446
|
-
mode: "SOLANA" | "ETHEREUM" = "ETHEREUM"
|
|
445
|
+
mode: "SOLANA" | "ETHEREUM" = "ETHEREUM",
|
|
447
446
|
): Promise<Hex> => {
|
|
448
447
|
if (!this.user) {
|
|
449
448
|
throw new NotAuthenticatedError();
|
|
@@ -496,7 +495,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
496
495
|
*/
|
|
497
496
|
public request = async <R extends SignerRoutes>(
|
|
498
497
|
route: R,
|
|
499
|
-
body: SignerBody<R
|
|
498
|
+
body: SignerBody<R>,
|
|
500
499
|
): Promise<SignerResponse<R>> => {
|
|
501
500
|
const url = this.connectionConfig.rpcUrl ?? "https://api.g.alchemy.com";
|
|
502
501
|
|
|
@@ -589,7 +588,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
589
588
|
});
|
|
590
589
|
default:
|
|
591
590
|
throw new Error(
|
|
592
|
-
`Unsupported MFA factor type: ${params.multiFactorType}
|
|
591
|
+
`Unsupported MFA factor type: ${params.multiFactorType}`,
|
|
593
592
|
);
|
|
594
593
|
}
|
|
595
594
|
};
|
|
@@ -602,7 +601,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
602
601
|
* @throws {NotAuthenticatedError} If no user is authenticated
|
|
603
602
|
*/
|
|
604
603
|
public verifyMfa = async (
|
|
605
|
-
params: VerifyMfaParams
|
|
604
|
+
params: VerifyMfaParams,
|
|
606
605
|
): Promise<{ multiFactors: MfaFactor[] }> => {
|
|
607
606
|
if (!this.user) {
|
|
608
607
|
throw new NotAuthenticatedError();
|
|
@@ -635,7 +634,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
635
634
|
* @throws {NotAuthenticatedError} If no user is authenticated
|
|
636
635
|
*/
|
|
637
636
|
public removeMfa = async (
|
|
638
|
-
params: RemoveMfaParams
|
|
637
|
+
params: RemoveMfaParams,
|
|
639
638
|
): Promise<{ multiFactors: MfaFactor[] }> => {
|
|
640
639
|
if (!this.user) {
|
|
641
640
|
throw new NotAuthenticatedError();
|
|
@@ -667,7 +666,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
667
666
|
* @throws {Error} If no credential bundle is returned from the server
|
|
668
667
|
*/
|
|
669
668
|
public validateMultiFactors = async (
|
|
670
|
-
params: ValidateMultiFactorsParams
|
|
669
|
+
params: ValidateMultiFactorsParams,
|
|
671
670
|
): Promise<{ bundle: string }> => {
|
|
672
671
|
// Send the encryptedPayload plus TOTP codes, etc:
|
|
673
672
|
const response = await this.request("/v1/auth-validate-multi-factors", {
|
|
@@ -678,7 +677,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
678
677
|
// The server is expected to return the *decrypted* payload in `response.payload.credentialBundle`
|
|
679
678
|
if (!response.payload || !response.payload.credentialBundle) {
|
|
680
679
|
throw new Error(
|
|
681
|
-
"Request to validateMultiFactors did not return a credential bundle"
|
|
680
|
+
"Request to validateMultiFactors did not return a credential bundle",
|
|
682
681
|
);
|
|
683
682
|
}
|
|
684
683
|
|
|
@@ -704,17 +703,17 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
704
703
|
this.turnkeyClient.getWalletAccounts({
|
|
705
704
|
organizationId: this.user!.orgId,
|
|
706
705
|
walletId,
|
|
707
|
-
})
|
|
708
|
-
)
|
|
706
|
+
}),
|
|
707
|
+
),
|
|
709
708
|
).then((x) => x.flatMap((x) => x.accounts));
|
|
710
709
|
|
|
711
710
|
const walletAccount = walletAccounts.find(
|
|
712
|
-
(x) => x.address === this.user!.address
|
|
711
|
+
(x) => x.address === this.user!.address,
|
|
713
712
|
);
|
|
714
713
|
|
|
715
714
|
if (!walletAccount) {
|
|
716
715
|
throw new Error(
|
|
717
|
-
`Could not find wallet associated with ${this.user.address}
|
|
716
|
+
`Could not find wallet associated with ${this.user.address}`,
|
|
718
717
|
);
|
|
719
718
|
}
|
|
720
719
|
|
|
@@ -731,7 +730,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
731
730
|
const { exportBundle } = await this.pollActivityCompletion(
|
|
732
731
|
activity,
|
|
733
732
|
this.user.orgId,
|
|
734
|
-
"exportWalletResult"
|
|
733
|
+
"exportWalletResult",
|
|
735
734
|
);
|
|
736
735
|
|
|
737
736
|
const result = await stamper.injectWalletExportBundle(exportBundle);
|
|
@@ -761,7 +760,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
761
760
|
const { exportBundle } = await this.pollActivityCompletion(
|
|
762
761
|
activity,
|
|
763
762
|
this.user.orgId,
|
|
764
|
-
"exportWalletAccountResult"
|
|
763
|
+
"exportWalletAccountResult",
|
|
765
764
|
);
|
|
766
765
|
|
|
767
766
|
const result = await stamper.injectKeyExportBundle(exportBundle);
|
|
@@ -807,7 +806,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
807
806
|
* @returns {Promise<string>} returns the Oauth provider's url
|
|
808
807
|
*/
|
|
809
808
|
protected getOauthProviderUrl = async (
|
|
810
|
-
args: GetOauthProviderUrlArgs
|
|
809
|
+
args: GetOauthProviderUrlArgs,
|
|
811
810
|
): Promise<string> => {
|
|
812
811
|
const {
|
|
813
812
|
oauthParams,
|
|
@@ -839,7 +838,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
839
838
|
const authProvider = authProviders.find(
|
|
840
839
|
(provider) =>
|
|
841
840
|
provider.id === authProviderId &&
|
|
842
|
-
!!provider.isCustomProvider === !!isCustomProvider
|
|
841
|
+
!!provider.isCustomProvider === !!isCustomProvider,
|
|
843
842
|
);
|
|
844
843
|
|
|
845
844
|
if (!authProvider) {
|
|
@@ -879,7 +878,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
879
878
|
openerOrigin: mode === "popup" ? window.location.origin : undefined,
|
|
880
879
|
};
|
|
881
880
|
const state = base64UrlEncode(
|
|
882
|
-
new TextEncoder().encode(JSON.stringify(stateObject))
|
|
881
|
+
new TextEncoder().encode(JSON.stringify(stateObject)),
|
|
883
882
|
);
|
|
884
883
|
const authUrl = new URL(authEndpoint);
|
|
885
884
|
const params: Record<string, string> = {
|
|
@@ -911,7 +910,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
911
910
|
};
|
|
912
911
|
|
|
913
912
|
private getOauthConfigForMode = async (
|
|
914
|
-
mode: OauthMode
|
|
913
|
+
mode: OauthMode,
|
|
915
914
|
): Promise<OauthConfig> => {
|
|
916
915
|
if (this.oauthConfig) {
|
|
917
916
|
return this.oauthConfig;
|
|
@@ -919,7 +918,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
919
918
|
return this.initOauth();
|
|
920
919
|
} else {
|
|
921
920
|
throw new Error(
|
|
922
|
-
"enablePopupOauth must be set in configuration or signer.preparePopupOauth must be called before using popup-based OAuth login"
|
|
921
|
+
"enablePopupOauth must be set in configuration or signer.preparePopupOauth must be called before using popup-based OAuth login",
|
|
923
922
|
);
|
|
924
923
|
}
|
|
925
924
|
};
|
|
@@ -928,13 +927,13 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
928
927
|
protected pollActivityCompletion = async <
|
|
929
928
|
T extends keyof Awaited<
|
|
930
929
|
ReturnType<(typeof this.turnkeyClient)["getActivity"]>
|
|
931
|
-
>["activity"]["result"]
|
|
930
|
+
>["activity"]["result"],
|
|
932
931
|
>(
|
|
933
932
|
activity: Awaited<
|
|
934
933
|
ReturnType<(typeof this.turnkeyClient)["getActivity"]>
|
|
935
934
|
>["activity"],
|
|
936
935
|
organizationId: string,
|
|
937
|
-
resultKey: T
|
|
936
|
+
resultKey: T,
|
|
938
937
|
): Promise<
|
|
939
938
|
NonNullable<
|
|
940
939
|
Awaited<
|
|
@@ -963,7 +962,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
963
962
|
status === "ACTIVITY_STATUS_CONSENSUS_NEEDED"
|
|
964
963
|
) {
|
|
965
964
|
throw new Error(
|
|
966
|
-
`Failed to get activity with with id ${id} (status: ${status})
|
|
965
|
+
`Failed to get activity with with id ${id} (status: ${status})`,
|
|
967
966
|
);
|
|
968
967
|
}
|
|
969
968
|
|