zksync-sso 0.0.0-beta.1
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/.gitignore +5 -0
- package/.lintstagedrc.js +5 -0
- package/.npmignore +10 -0
- package/README.md +3 -0
- package/dist/_cjs/abi/Factory.js +197 -0
- package/dist/_cjs/abi/Factory.js.map +1 -0
- package/dist/_cjs/abi/SessionKeyModule.js +1104 -0
- package/dist/_cjs/abi/SessionKeyModule.js.map +1 -0
- package/dist/_cjs/client/actions/account.js +140 -0
- package/dist/_cjs/client/actions/account.js.map +1 -0
- package/dist/_cjs/client/actions/index.js +19 -0
- package/dist/_cjs/client/actions/index.js.map +1 -0
- package/dist/_cjs/client/actions/passkey.js +122 -0
- package/dist/_cjs/client/actions/passkey.js.map +1 -0
- package/dist/_cjs/client/actions/session.js +40 -0
- package/dist/_cjs/client/actions/session.js.map +1 -0
- package/dist/_cjs/client/clients/passkey.js +46 -0
- package/dist/_cjs/client/clients/passkey.js.map +1 -0
- package/dist/_cjs/client/clients/session.js +48 -0
- package/dist/_cjs/client/clients/session.js.map +1 -0
- package/dist/_cjs/client/decorators/index.js +19 -0
- package/dist/_cjs/client/decorators/index.js.map +1 -0
- package/dist/_cjs/client/decorators/passkey.js +15 -0
- package/dist/_cjs/client/decorators/passkey.js.map +1 -0
- package/dist/_cjs/client/decorators/session.js +7 -0
- package/dist/_cjs/client/decorators/session.js.map +1 -0
- package/dist/_cjs/client/decorators/session_wallet.js +32 -0
- package/dist/_cjs/client/decorators/session_wallet.js.map +1 -0
- package/dist/_cjs/client/index.js +22 -0
- package/dist/_cjs/client/index.js.map +1 -0
- package/dist/_cjs/client/passkey.js +20 -0
- package/dist/_cjs/client/passkey.js.map +1 -0
- package/dist/_cjs/client/smart-account.js +45 -0
- package/dist/_cjs/client/smart-account.js.map +1 -0
- package/dist/_cjs/client/utils/assertEip712Transaction.js +44 -0
- package/dist/_cjs/client/utils/assertEip712Transaction.js.map +1 -0
- package/dist/_cjs/client/utils/getEip712Domain.js +57 -0
- package/dist/_cjs/client/utils/getEip712Domain.js.map +1 -0
- package/dist/_cjs/client/utils/isEip712Transaction.js +16 -0
- package/dist/_cjs/client/utils/isEip712Transaction.js.map +1 -0
- package/dist/_cjs/client-auth-server/Signer.js +264 -0
- package/dist/_cjs/client-auth-server/Signer.js.map +1 -0
- package/dist/_cjs/client-auth-server/WalletProvider.js +107 -0
- package/dist/_cjs/client-auth-server/WalletProvider.js.map +1 -0
- package/dist/_cjs/client-auth-server/index.js +20 -0
- package/dist/_cjs/client-auth-server/index.js.map +1 -0
- package/dist/_cjs/client-auth-server/interface.js +3 -0
- package/dist/_cjs/client-auth-server/interface.js.map +1 -0
- package/dist/_cjs/client-auth-server/rpc.js +3 -0
- package/dist/_cjs/client-auth-server/rpc.js.map +1 -0
- package/dist/_cjs/client-auth-server/session.js +90 -0
- package/dist/_cjs/client-auth-server/session.js.map +1 -0
- package/dist/_cjs/communicator/PopupCommunicator.js +138 -0
- package/dist/_cjs/communicator/PopupCommunicator.js.map +1 -0
- package/dist/_cjs/communicator/index.js +6 -0
- package/dist/_cjs/communicator/index.js.map +1 -0
- package/dist/_cjs/communicator/interface.js +3 -0
- package/dist/_cjs/communicator/interface.js.map +1 -0
- package/dist/_cjs/connector/index.js +148 -0
- package/dist/_cjs/connector/index.js.map +1 -0
- package/dist/_cjs/errors/constants.js +97 -0
- package/dist/_cjs/errors/constants.js.map +1 -0
- package/dist/_cjs/errors/errors.js +122 -0
- package/dist/_cjs/errors/errors.js.map +1 -0
- package/dist/_cjs/errors/index.js +10 -0
- package/dist/_cjs/errors/index.js.map +1 -0
- package/dist/_cjs/errors/serialize.js +63 -0
- package/dist/_cjs/errors/serialize.js.map +1 -0
- package/dist/_cjs/errors/utils.js +95 -0
- package/dist/_cjs/errors/utils.js.map +1 -0
- package/dist/_cjs/index.js +6 -0
- package/dist/_cjs/index.js.map +1 -0
- package/dist/_cjs/package.json +1 -0
- package/dist/_cjs/utils/encoding.js +32 -0
- package/dist/_cjs/utils/encoding.js.map +1 -0
- package/dist/_cjs/utils/helpers.js +43 -0
- package/dist/_cjs/utils/helpers.js.map +1 -0
- package/dist/_cjs/utils/index.js +20 -0
- package/dist/_cjs/utils/index.js.map +1 -0
- package/dist/_cjs/utils/passkey.js +243 -0
- package/dist/_cjs/utils/passkey.js.map +1 -0
- package/dist/_cjs/utils/session.js +30 -0
- package/dist/_cjs/utils/session.js.map +1 -0
- package/dist/_cjs/utils/storage.js +93 -0
- package/dist/_cjs/utils/storage.js.map +1 -0
- package/dist/_cjs/version.js +5 -0
- package/dist/_cjs/version.js.map +1 -0
- package/dist/_esm/abi/Factory.js +194 -0
- package/dist/_esm/abi/Factory.js.map +1 -0
- package/dist/_esm/abi/SessionKeyModule.js +1101 -0
- package/dist/_esm/abi/SessionKeyModule.js.map +1 -0
- package/dist/_esm/client/actions/account.js +137 -0
- package/dist/_esm/client/actions/account.js.map +1 -0
- package/dist/_esm/client/actions/index.js +3 -0
- package/dist/_esm/client/actions/index.js.map +1 -0
- package/dist/_esm/client/actions/passkey.js +121 -0
- package/dist/_esm/client/actions/passkey.js.map +1 -0
- package/dist/_esm/client/actions/session.js +36 -0
- package/dist/_esm/client/actions/session.js.map +1 -0
- package/dist/_esm/client/clients/passkey.js +43 -0
- package/dist/_esm/client/clients/passkey.js.map +1 -0
- package/dist/_esm/client/clients/session.js +45 -0
- package/dist/_esm/client/clients/session.js.map +1 -0
- package/dist/_esm/client/decorators/index.js +3 -0
- package/dist/_esm/client/decorators/index.js.map +1 -0
- package/dist/_esm/client/decorators/passkey.js +13 -0
- package/dist/_esm/client/decorators/passkey.js.map +1 -0
- package/dist/_esm/client/decorators/session.js +5 -0
- package/dist/_esm/client/decorators/session.js.map +1 -0
- package/dist/_esm/client/decorators/session_wallet.js +171 -0
- package/dist/_esm/client/decorators/session_wallet.js.map +1 -0
- package/dist/_esm/client/index.js +3 -0
- package/dist/_esm/client/index.js.map +1 -0
- package/dist/_esm/client/passkey.js +4 -0
- package/dist/_esm/client/passkey.js.map +1 -0
- package/dist/_esm/client/smart-account.js +46 -0
- package/dist/_esm/client/smart-account.js.map +1 -0
- package/dist/_esm/client/utils/assertEip712Transaction.js +39 -0
- package/dist/_esm/client/utils/assertEip712Transaction.js.map +1 -0
- package/dist/_esm/client/utils/getEip712Domain.js +57 -0
- package/dist/_esm/client/utils/getEip712Domain.js.map +1 -0
- package/dist/_esm/client/utils/isEip712Transaction.js +13 -0
- package/dist/_esm/client/utils/isEip712Transaction.js.map +1 -0
- package/dist/_esm/client-auth-server/Signer.js +262 -0
- package/dist/_esm/client-auth-server/Signer.js.map +1 -0
- package/dist/_esm/client-auth-server/WalletProvider.js +104 -0
- package/dist/_esm/client-auth-server/WalletProvider.js.map +1 -0
- package/dist/_esm/client-auth-server/index.js +4 -0
- package/dist/_esm/client-auth-server/index.js.map +1 -0
- package/dist/_esm/client-auth-server/interface.js +2 -0
- package/dist/_esm/client-auth-server/interface.js.map +1 -0
- package/dist/_esm/client-auth-server/rpc.js +2 -0
- package/dist/_esm/client-auth-server/rpc.js.map +1 -0
- package/dist/_esm/client-auth-server/session.js +91 -0
- package/dist/_esm/client-auth-server/session.js.map +1 -0
- package/dist/_esm/communicator/PopupCommunicator.js +136 -0
- package/dist/_esm/communicator/PopupCommunicator.js.map +1 -0
- package/dist/_esm/communicator/index.js +2 -0
- package/dist/_esm/communicator/index.js.map +1 -0
- package/dist/_esm/communicator/interface.js +2 -0
- package/dist/_esm/communicator/interface.js.map +1 -0
- package/dist/_esm/connector/index.js +146 -0
- package/dist/_esm/connector/index.js.map +1 -0
- package/dist/_esm/errors/constants.js +94 -0
- package/dist/_esm/errors/constants.js.map +1 -0
- package/dist/_esm/errors/errors.js +124 -0
- package/dist/_esm/errors/errors.js.map +1 -0
- package/dist/_esm/errors/index.js +4 -0
- package/dist/_esm/errors/index.js.map +1 -0
- package/dist/_esm/errors/serialize.js +69 -0
- package/dist/_esm/errors/serialize.js.map +1 -0
- package/dist/_esm/errors/utils.js +101 -0
- package/dist/_esm/errors/utils.js.map +1 -0
- package/dist/_esm/index.js +2 -0
- package/dist/_esm/index.js.map +1 -0
- package/dist/_esm/package.json +1 -0
- package/dist/_esm/utils/encoding.js +26 -0
- package/dist/_esm/utils/encoding.js.map +1 -0
- package/dist/_esm/utils/helpers.js +40 -0
- package/dist/_esm/utils/helpers.js.map +1 -0
- package/dist/_esm/utils/index.js +4 -0
- package/dist/_esm/utils/index.js.map +1 -0
- package/dist/_esm/utils/passkey.js +294 -0
- package/dist/_esm/utils/passkey.js.map +1 -0
- package/dist/_esm/utils/session.js +31 -0
- package/dist/_esm/utils/session.js.map +1 -0
- package/dist/_esm/utils/storage.js +89 -0
- package/dist/_esm/utils/storage.js.map +1 -0
- package/dist/_esm/version.js +2 -0
- package/dist/_esm/version.js.map +1 -0
- package/dist/_types/abi/Factory.d.ts +149 -0
- package/dist/_types/abi/Factory.d.ts.map +1 -0
- package/dist/_types/abi/SessionKeyModule.d.ts +846 -0
- package/dist/_types/abi/SessionKeyModule.d.ts.map +1 -0
- package/dist/_types/client/actions/account.d.ts +38 -0
- package/dist/_types/client/actions/account.d.ts.map +1 -0
- package/dist/_types/client/actions/index.d.ts +3 -0
- package/dist/_types/client/actions/index.d.ts.map +1 -0
- package/dist/_types/client/actions/passkey.d.ts +45 -0
- package/dist/_types/client/actions/passkey.d.ts.map +1 -0
- package/dist/_types/client/actions/session.d.ts +14 -0
- package/dist/_types/client/actions/session.d.ts.map +1 -0
- package/dist/_types/client/clients/passkey.d.ts +32 -0
- package/dist/_types/client/clients/passkey.d.ts.map +1 -0
- package/dist/_types/client/clients/session.d.ts +26 -0
- package/dist/_types/client/clients/session.d.ts.map +1 -0
- package/dist/_types/client/decorators/index.d.ts +3 -0
- package/dist/_types/client/decorators/index.d.ts.map +1 -0
- package/dist/_types/client/decorators/passkey.d.ts +8 -0
- package/dist/_types/client/decorators/passkey.d.ts.map +1 -0
- package/dist/_types/client/decorators/session.d.ts +5 -0
- package/dist/_types/client/decorators/session.d.ts.map +1 -0
- package/dist/_types/client/decorators/session_wallet.d.ts +5 -0
- package/dist/_types/client/decorators/session_wallet.d.ts.map +1 -0
- package/dist/_types/client/index.d.ts +3 -0
- package/dist/_types/client/index.d.ts.map +1 -0
- package/dist/_types/client/passkey.d.ts +4 -0
- package/dist/_types/client/passkey.d.ts.map +1 -0
- package/dist/_types/client/smart-account.d.ts +24 -0
- package/dist/_types/client/smart-account.d.ts.map +1 -0
- package/dist/_types/client/utils/assertEip712Transaction.d.ts +11 -0
- package/dist/_types/client/utils/assertEip712Transaction.d.ts.map +1 -0
- package/dist/_types/client/utils/getEip712Domain.d.ts +3 -0
- package/dist/_types/client/utils/getEip712Domain.d.ts.map +1 -0
- package/dist/_types/client/utils/isEip712Transaction.d.ts +4 -0
- package/dist/_types/client/utils/isEip712Transaction.d.ts.map +1 -0
- package/dist/_types/client-auth-server/Signer.d.ts +52 -0
- package/dist/_types/client-auth-server/Signer.d.ts.map +1 -0
- package/dist/_types/client-auth-server/WalletProvider.d.ts +27 -0
- package/dist/_types/client-auth-server/WalletProvider.d.ts.map +1 -0
- package/dist/_types/client-auth-server/index.d.ts +4 -0
- package/dist/_types/client-auth-server/index.d.ts.map +1 -0
- package/dist/_types/client-auth-server/interface.d.ts +34 -0
- package/dist/_types/client-auth-server/interface.d.ts.map +1 -0
- package/dist/_types/client-auth-server/rpc.d.ts +55 -0
- package/dist/_types/client-auth-server/rpc.d.ts.map +1 -0
- package/dist/_types/client-auth-server/session.d.ts +45 -0
- package/dist/_types/client-auth-server/session.d.ts.map +1 -0
- package/dist/_types/communicator/PopupCommunicator.d.ts +20 -0
- package/dist/_types/communicator/PopupCommunicator.d.ts.map +1 -0
- package/dist/_types/communicator/index.d.ts +3 -0
- package/dist/_types/communicator/index.d.ts.map +1 -0
- package/dist/_types/communicator/interface.d.ts +16 -0
- package/dist/_types/communicator/interface.d.ts.map +1 -0
- package/dist/_types/connector/index.d.ts +8 -0
- package/dist/_types/connector/index.d.ts.map +1 -0
- package/dist/_types/errors/constants.d.ts +96 -0
- package/dist/_types/errors/constants.d.ts.map +1 -0
- package/dist/_types/errors/errors.d.ts +48 -0
- package/dist/_types/errors/errors.d.ts.map +1 -0
- package/dist/_types/errors/index.d.ts +5 -0
- package/dist/_types/errors/index.d.ts.map +1 -0
- package/dist/_types/errors/serialize.d.ts +13 -0
- package/dist/_types/errors/serialize.d.ts.map +1 -0
- package/dist/_types/errors/utils.d.ts +30 -0
- package/dist/_types/errors/utils.d.ts.map +1 -0
- package/dist/_types/index.d.ts +4 -0
- package/dist/_types/index.d.ts.map +1 -0
- package/dist/_types/utils/encoding.d.ts +12 -0
- package/dist/_types/utils/encoding.d.ts.map +1 -0
- package/dist/_types/utils/helpers.d.ts +4 -0
- package/dist/_types/utils/helpers.d.ts.map +1 -0
- package/dist/_types/utils/index.d.ts +4 -0
- package/dist/_types/utils/index.d.ts.map +1 -0
- package/dist/_types/utils/passkey.d.ts +47 -0
- package/dist/_types/utils/passkey.d.ts.map +1 -0
- package/dist/_types/utils/session.d.ts +95 -0
- package/dist/_types/utils/session.d.ts.map +1 -0
- package/dist/_types/utils/storage.d.ts +30 -0
- package/dist/_types/utils/storage.d.ts.map +1 -0
- package/dist/_types/version.d.ts +2 -0
- package/dist/_types/version.d.ts.map +1 -0
- package/eslint.config.js +6 -0
- package/package.json +144 -0
- package/prepare-package.mjs +39 -0
- package/project.json +67 -0
- package/src/abi/Factory.ts +193 -0
- package/src/abi/SessionKeyModule.ts +1100 -0
- package/src/client/actions/account.ts +198 -0
- package/src/client/actions/index.ts +2 -0
- package/src/client/actions/passkey.ts +165 -0
- package/src/client/actions/session.ts +118 -0
- package/src/client/clients/passkey.ts +107 -0
- package/src/client/clients/session.ts +105 -0
- package/src/client/decorators/index.ts +2 -0
- package/src/client/decorators/passkey.ts +22 -0
- package/src/client/decorators/session.ts +17 -0
- package/src/client/decorators/session_wallet.ts +184 -0
- package/src/client/index.ts +2 -0
- package/src/client/passkey.ts +3 -0
- package/src/client/smart-account.ts +68 -0
- package/src/client/utils/assertEip712Transaction.ts +49 -0
- package/src/client/utils/getEip712Domain.ts +84 -0
- package/src/client/utils/isEip712Transaction.ts +18 -0
- package/src/client-auth-server/Signer.ts +260 -0
- package/src/client-auth-server/WalletProvider.ts +114 -0
- package/src/client-auth-server/index.ts +3 -0
- package/src/client-auth-server/interface.ts +39 -0
- package/src/client-auth-server/rpc.ts +69 -0
- package/src/client-auth-server/session.ts +139 -0
- package/src/communicator/PopupCommunicator.ts +111 -0
- package/src/communicator/index.ts +2 -0
- package/src/communicator/interface.ts +15 -0
- package/src/connector/index.ts +171 -0
- package/src/errors/constants.ts +119 -0
- package/src/errors/errors.ts +168 -0
- package/src/errors/index.ts +4 -0
- package/src/errors/serialize.ts +91 -0
- package/src/errors/utils.ts +152 -0
- package/src/index.ts +3 -0
- package/src/types/index.d.ts +9 -0
- package/src/utils/encoding.ts +36 -0
- package/src/utils/helpers.ts +43 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/passkey.ts +344 -0
- package/src/utils/session.ts +103 -0
- package/src/utils/storage.ts +87 -0
- package/src/version.ts +1 -0
- package/tsconfig.base.json +44 -0
- package/tsconfig.json +11 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { errorValues, standardErrorCodes } from "./constants.js";
|
|
2
|
+
|
|
3
|
+
const FALLBACK_MESSAGE = "Unspecified error message.";
|
|
4
|
+
|
|
5
|
+
const JSON_RPC_SERVER_ERROR_MESSAGE = "Unspecified server error.";
|
|
6
|
+
|
|
7
|
+
type ErrorValueKey = keyof typeof errorValues;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Gets the message for a given code, or a fallback message if the code has
|
|
11
|
+
* no corresponding message.
|
|
12
|
+
*/
|
|
13
|
+
export function getMessageFromCode(
|
|
14
|
+
code: number | undefined,
|
|
15
|
+
fallbackMessage: string = FALLBACK_MESSAGE,
|
|
16
|
+
): string {
|
|
17
|
+
if (code && Number.isInteger(code)) {
|
|
18
|
+
const codeString = code.toString();
|
|
19
|
+
|
|
20
|
+
if (hasKey(errorValues, codeString)) {
|
|
21
|
+
return errorValues[codeString as ErrorValueKey].message;
|
|
22
|
+
}
|
|
23
|
+
if (isJsonRpcServerError(code)) {
|
|
24
|
+
return JSON_RPC_SERVER_ERROR_MESSAGE;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return fallbackMessage;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Returns whether the given code is valid.
|
|
32
|
+
* A code is only valid if it has a message.
|
|
33
|
+
*/
|
|
34
|
+
export function isValidCode(code: number): boolean {
|
|
35
|
+
if (!Number.isInteger(code)) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const codeString = code.toString();
|
|
40
|
+
if (errorValues[codeString as ErrorValueKey]) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (isJsonRpcServerError(code)) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Returns the error code from an error object.
|
|
52
|
+
*/
|
|
53
|
+
export function getErrorCode(error: unknown): number | undefined {
|
|
54
|
+
if (typeof error === "number") {
|
|
55
|
+
return error;
|
|
56
|
+
} else if (isErrorWithCode(error)) {
|
|
57
|
+
return error.code ?? error.errorCode;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
interface ErrorWithCode {
|
|
64
|
+
code?: number;
|
|
65
|
+
errorCode?: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function isErrorWithCode(error: unknown): error is ErrorWithCode {
|
|
69
|
+
return (
|
|
70
|
+
typeof error === "object"
|
|
71
|
+
&& error !== null
|
|
72
|
+
&& (typeof (error as ErrorWithCode).code === "number"
|
|
73
|
+
|| typeof (error as ErrorWithCode).errorCode === "number")
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Serializes the given error to an Ethereum JSON RPC-compatible error object.
|
|
79
|
+
* Merely copies the given error's values if it is already compatible.
|
|
80
|
+
* If the given error is not fully compatible, it will be preserved on the
|
|
81
|
+
* returned object's data.originalError property.
|
|
82
|
+
*/
|
|
83
|
+
|
|
84
|
+
export interface SerializedEthereumRpcError {
|
|
85
|
+
code: number; // must be an integer
|
|
86
|
+
message: string;
|
|
87
|
+
data?: unknown;
|
|
88
|
+
stack?: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function serialize(
|
|
92
|
+
error: unknown,
|
|
93
|
+
{ shouldIncludeStack = false } = {},
|
|
94
|
+
): SerializedEthereumRpcError {
|
|
95
|
+
const serialized: Partial<SerializedEthereumRpcError> = {};
|
|
96
|
+
|
|
97
|
+
if (
|
|
98
|
+
error
|
|
99
|
+
&& typeof error === "object"
|
|
100
|
+
&& !Array.isArray(error)
|
|
101
|
+
&& hasKey(error as Record<string, unknown>, "code")
|
|
102
|
+
&& isValidCode((error as SerializedEthereumRpcError).code)
|
|
103
|
+
) {
|
|
104
|
+
const _error = error as Partial<SerializedEthereumRpcError>;
|
|
105
|
+
serialized.code = _error.code;
|
|
106
|
+
|
|
107
|
+
if (_error.message && typeof _error.message === "string") {
|
|
108
|
+
serialized.message = _error.message;
|
|
109
|
+
|
|
110
|
+
if (hasKey(_error, "data")) {
|
|
111
|
+
serialized.data = _error.data;
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
serialized.message = getMessageFromCode((serialized as SerializedEthereumRpcError).code);
|
|
115
|
+
|
|
116
|
+
serialized.data = { originalError: assignOriginalError(error) };
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
serialized.code = standardErrorCodes.rpc.internal;
|
|
120
|
+
|
|
121
|
+
serialized.message = hasStringProperty(error, "message") ? error.message : FALLBACK_MESSAGE;
|
|
122
|
+
serialized.data = { originalError: assignOriginalError(error) };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (shouldIncludeStack) {
|
|
126
|
+
serialized.stack = hasStringProperty(error, "stack") ? error.stack : undefined;
|
|
127
|
+
}
|
|
128
|
+
return serialized as SerializedEthereumRpcError;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Internal
|
|
132
|
+
|
|
133
|
+
function isJsonRpcServerError(code: number): boolean {
|
|
134
|
+
return code >= -32099 && code <= -32000;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function assignOriginalError(error: unknown): unknown {
|
|
138
|
+
if (error && typeof error === "object" && !Array.isArray(error)) {
|
|
139
|
+
return Object.assign({}, error);
|
|
140
|
+
}
|
|
141
|
+
return error;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function hasKey(obj: Record<string, unknown>, key: string) {
|
|
145
|
+
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function hasStringProperty<T>(obj: unknown, prop: keyof T): obj is T {
|
|
149
|
+
return (
|
|
150
|
+
typeof obj === "object" && obj !== null && prop in obj && typeof (obj as T)[prop] === "string"
|
|
151
|
+
);
|
|
152
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export type { AppMetadata, ProviderInterface } from "./client-auth-server/interface.js";
|
|
2
|
+
export type { SessionPreferences } from "./client-auth-server/session.js";
|
|
3
|
+
export { WalletProvider, type WalletProviderConstructorOptions } from "./client-auth-server/WalletProvider.js";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type Address, encodeAbiParameters, encodeFunctionData, type Hash, type Hex, parseAbiParameters, toHex } from "viem";
|
|
2
|
+
|
|
3
|
+
import { SessionKeyModuleAbi } from "../abi/SessionKeyModule.js";
|
|
4
|
+
import type { SessionConfig } from "../utils/session.js";
|
|
5
|
+
|
|
6
|
+
export const encodeSession = (sessionConfig: SessionConfig) => {
|
|
7
|
+
const callData = encodeFunctionData({
|
|
8
|
+
abi: SessionKeyModuleAbi,
|
|
9
|
+
functionName: "createSession",
|
|
10
|
+
args: [sessionConfig],
|
|
11
|
+
});
|
|
12
|
+
const selector = callData.slice(0, "0x".length + 8) as Hex; // first 4 bytes for function selector
|
|
13
|
+
const args = `0x${callData.slice(selector.length, callData.length)}` as Hex; // the rest is the arguments
|
|
14
|
+
return args;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const encodePasskeyModuleParameters = (passkey: { passkeyPublicKey: [Buffer, Buffer]; expectedOrigin: string }) => {
|
|
18
|
+
return encodeAbiParameters(
|
|
19
|
+
[
|
|
20
|
+
{ type: "bytes32[2]", name: "xyPublicKeys" },
|
|
21
|
+
{ type: "string", name: "expectedOrigin" },
|
|
22
|
+
],
|
|
23
|
+
[
|
|
24
|
+
[toHex(passkey.passkeyPublicKey[0]), toHex(passkey.passkeyPublicKey[1])],
|
|
25
|
+
passkey.expectedOrigin,
|
|
26
|
+
],
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const encodeModuleData = (moduleData: { address: Address; parameters: Hash }) => {
|
|
31
|
+
const moduleParams = parseAbiParameters("address, bytes");
|
|
32
|
+
return encodeAbiParameters(
|
|
33
|
+
moduleParams,
|
|
34
|
+
[moduleData.address, moduleData.parameters],
|
|
35
|
+
);
|
|
36
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export function getWebsiteName(): string | null {
|
|
2
|
+
const fullTitle = document.title;
|
|
3
|
+
if (!fullTitle) return null;
|
|
4
|
+
|
|
5
|
+
const delimiters = [" - ", " | ", " : ", " · ", " — "];
|
|
6
|
+
|
|
7
|
+
// Find the first delimiter that splits the title
|
|
8
|
+
for (const delimiter of delimiters) {
|
|
9
|
+
const parts = fullTitle.split(delimiter);
|
|
10
|
+
if (parts.length > 1) {
|
|
11
|
+
return parts[0]!.trim();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return fullTitle.trim();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function getFavicon(): string | null {
|
|
19
|
+
const el = document.querySelector(
|
|
20
|
+
"link[sizes=\"192x192\"], link[sizes=\"180x180\"], link[rel=\"icon\"], link[rel=\"shortcut icon\"]",
|
|
21
|
+
);
|
|
22
|
+
const href = el?.getAttribute("href");
|
|
23
|
+
if (!href) return null;
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const url = new URL(href, document.location.href);
|
|
27
|
+
// Make sure no malicious URLs are returned like "javascript:..."
|
|
28
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
return url.href;
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function noThrow<T>(fn: () => T): T | null {
|
|
38
|
+
try {
|
|
39
|
+
return fn();
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import { ECDSASigValue } from "@peculiar/asn1-ecc";
|
|
2
|
+
import { AsnParser } from "@peculiar/asn1-schema";
|
|
3
|
+
import { bigintToBuf, bufToBigint } from "bigint-conversion";
|
|
4
|
+
import { Buffer } from "buffer";
|
|
5
|
+
import { type Address, encodeAbiParameters, type Hex, toHex } from "viem";
|
|
6
|
+
|
|
7
|
+
enum COSEKEYS {
|
|
8
|
+
kty = 1, // Key Type
|
|
9
|
+
alg = 3, // Algorithm
|
|
10
|
+
crv = -1, // Curve for EC keys
|
|
11
|
+
x = -2, // X coordinate for EC keys
|
|
12
|
+
y = -3, // Y coordinate for EC keys
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type COSEPublicKeyMap = Map<COSEKEYS, number | Buffer>;
|
|
16
|
+
|
|
17
|
+
// Encode an integer in CBOR format
|
|
18
|
+
function encodeInt(int: number): Buffer {
|
|
19
|
+
if (int >= 0 && int <= 23) {
|
|
20
|
+
// Small positive integer (0–23)
|
|
21
|
+
return Buffer.from([int]);
|
|
22
|
+
} else if (int >= 24 && int <= 255) {
|
|
23
|
+
// 1-byte positive integer
|
|
24
|
+
return Buffer.from([0x18, int]);
|
|
25
|
+
} else if (int >= 256 && int <= 65535) {
|
|
26
|
+
// 2-byte positive integer
|
|
27
|
+
const buf = Buffer.alloc(3);
|
|
28
|
+
buf[0] = 0x19;
|
|
29
|
+
buf.writeUInt16BE(int, 1);
|
|
30
|
+
return buf;
|
|
31
|
+
} else if (int < 0 && int >= -24) {
|
|
32
|
+
// Small negative integer (-1 to -24)
|
|
33
|
+
return Buffer.from([0x20 - (int + 1)]);
|
|
34
|
+
} else if (int < -24 && int >= -256) {
|
|
35
|
+
// 1-byte negative integer
|
|
36
|
+
return Buffer.from([0x38, -int - 1]);
|
|
37
|
+
} else if (int < -256 && int >= -65536) {
|
|
38
|
+
// 2-byte negative integer
|
|
39
|
+
const buf = Buffer.alloc(3);
|
|
40
|
+
buf[0] = 0x39;
|
|
41
|
+
buf.writeUInt16BE(-int - 1, 1);
|
|
42
|
+
return buf;
|
|
43
|
+
} else {
|
|
44
|
+
throw new Error("Unsupported integer range");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Encode a byte array in CBOR format
|
|
49
|
+
function encodeBytes(bytes: Buffer): Buffer {
|
|
50
|
+
if (bytes.length <= 23) {
|
|
51
|
+
return Buffer.concat([Buffer.from([0x40 + bytes.length]), bytes]); // Byte array with small length
|
|
52
|
+
} else if (bytes.length < 256) {
|
|
53
|
+
return Buffer.concat([Buffer.from([0x58, bytes.length]), bytes]); // Byte array with 1-byte length prefix
|
|
54
|
+
} else {
|
|
55
|
+
throw new Error("Unsupported byte array length");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Encode a map in CBOR format
|
|
60
|
+
function encodeMap(map: COSEPublicKeyMap): Buffer {
|
|
61
|
+
const encodedItems: Buffer[] = [];
|
|
62
|
+
|
|
63
|
+
// CBOR map header, assuming the map size fits within small integer encoding
|
|
64
|
+
const mapHeader = 0xA0 | map.size;
|
|
65
|
+
encodedItems.push(Buffer.from([mapHeader]));
|
|
66
|
+
|
|
67
|
+
map.forEach((value, key) => {
|
|
68
|
+
// Encode the key
|
|
69
|
+
encodedItems.push(encodeInt(key));
|
|
70
|
+
|
|
71
|
+
// Encode the value based on its type (Buffer or number)
|
|
72
|
+
if (Buffer.isBuffer(value)) {
|
|
73
|
+
encodedItems.push(encodeBytes(value));
|
|
74
|
+
} else {
|
|
75
|
+
encodedItems.push(encodeInt(value));
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return Buffer.concat(encodedItems);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function decodeMap(buffer: Buffer): COSEPublicKeyMap {
|
|
83
|
+
const map = new Map<COSEKEYS, number | Buffer>();
|
|
84
|
+
let offset = 1; // Start after the map header
|
|
85
|
+
|
|
86
|
+
const mapHeader = buffer[0];
|
|
87
|
+
const mapSize = mapHeader & 0x1F; // Number of pairs
|
|
88
|
+
|
|
89
|
+
for (let i = 0; i < mapSize; i++) {
|
|
90
|
+
const [key, keyLength] = decodeInt(buffer, offset);
|
|
91
|
+
offset += keyLength;
|
|
92
|
+
|
|
93
|
+
const [value, valueLength] = decodeValue(buffer, offset);
|
|
94
|
+
offset += valueLength;
|
|
95
|
+
|
|
96
|
+
map.set(key as COSEKEYS, value);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return map;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function decodeInt(buffer: Buffer, offset: number): [number, number] {
|
|
103
|
+
const intByte = buffer[offset];
|
|
104
|
+
|
|
105
|
+
if (intByte < 24) {
|
|
106
|
+
// Small positive integer (0–23)
|
|
107
|
+
return [intByte, 1];
|
|
108
|
+
} else if (intByte === 0x18) {
|
|
109
|
+
// 1-byte unsigned integer
|
|
110
|
+
return [buffer[offset + 1], 2];
|
|
111
|
+
} else if (intByte === 0x19) {
|
|
112
|
+
// 2-byte unsigned integer
|
|
113
|
+
return [buffer.readUInt16BE(offset + 1), 3];
|
|
114
|
+
} else if (intByte >= 0x20 && intByte <= 0x37) {
|
|
115
|
+
// Small negative integer (-1 to -24)
|
|
116
|
+
return [-(intByte - 0x20) - 1, 1];
|
|
117
|
+
} else if (intByte === 0x38) {
|
|
118
|
+
// 1-byte negative integer
|
|
119
|
+
return [-1 - buffer[offset + 1], 2];
|
|
120
|
+
} else if (intByte === 0x39) {
|
|
121
|
+
// 2-byte negative integer
|
|
122
|
+
return [-1 - buffer.readUInt16BE(offset + 1), 3];
|
|
123
|
+
} else {
|
|
124
|
+
throw new Error("Unsupported integer format");
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function decodeBytes(buffer: Buffer, offset: number): [Buffer, number] {
|
|
129
|
+
const lengthByte = buffer[offset];
|
|
130
|
+
if (lengthByte >= 0x40 && lengthByte <= 0x57) {
|
|
131
|
+
const length = lengthByte - 0x40;
|
|
132
|
+
return [buffer.slice(offset + 1, offset + 1 + length), length + 1];
|
|
133
|
+
} else if (lengthByte === 0x58) { // Byte array with 1-byte length prefix
|
|
134
|
+
const length = buffer[offset + 1];
|
|
135
|
+
return [buffer.slice(offset + 2, offset + 2 + length), length + 2];
|
|
136
|
+
} else {
|
|
137
|
+
throw new Error("Unsupported byte format");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function decodeValue(buffer: Buffer, offset: number): [number | Buffer, number] {
|
|
142
|
+
const type = buffer[offset];
|
|
143
|
+
if (type >= 0x40 && type <= 0x5F) { // Byte array
|
|
144
|
+
return decodeBytes(buffer, offset);
|
|
145
|
+
} else {
|
|
146
|
+
return decodeInt(buffer, offset);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export const getPublicKeyBytesFromPasskeySignature = (publicPasskey: Uint8Array): [Buffer, Buffer] => {
|
|
151
|
+
const cosePublicKey = decodeMap(Buffer.from(publicPasskey)); // Decodes CBOR-encoded COSE key
|
|
152
|
+
const x = cosePublicKey.get(COSEKEYS.x) as Buffer;
|
|
153
|
+
const y = cosePublicKey.get(COSEKEYS.y) as Buffer;
|
|
154
|
+
|
|
155
|
+
return [Buffer.from(x), Buffer.from(y)];
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export const getPasskeySignatureFromPublicKeyBytes = (coordinates: [Hex, Hex]): Uint8Array => {
|
|
159
|
+
const [xHex, yHex] = coordinates;
|
|
160
|
+
const x = Buffer.from(xHex.slice(2), "hex");
|
|
161
|
+
const y = Buffer.from(yHex.slice(2), "hex");
|
|
162
|
+
|
|
163
|
+
const cosePublicKey: COSEPublicKeyMap = new Map();
|
|
164
|
+
cosePublicKey.set(COSEKEYS.kty, 2); // Type 2 for EC keys
|
|
165
|
+
cosePublicKey.set(COSEKEYS.alg, -7); // -7 for ES256 algorithm
|
|
166
|
+
cosePublicKey.set(COSEKEYS.crv, 1); // Curve ID (1 for P-256)
|
|
167
|
+
cosePublicKey.set(COSEKEYS.x, x);
|
|
168
|
+
cosePublicKey.set(COSEKEYS.y, y);
|
|
169
|
+
|
|
170
|
+
const encodedPublicKey = encodeMap(cosePublicKey);
|
|
171
|
+
return new Uint8Array(encodedPublicKey);
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Return 2 32byte words for the R & S for the EC2 signature, 0 l-trimmed
|
|
176
|
+
* @param signature
|
|
177
|
+
* @returns r & s bytes sequentially
|
|
178
|
+
*/
|
|
179
|
+
export function unwrapEC2Signature(signature: Uint8Array): { r: Uint8Array; s: Uint8Array } {
|
|
180
|
+
const parsedSignature = AsnParser.parse(signature, ECDSASigValue);
|
|
181
|
+
let rBytes = new Uint8Array(parsedSignature.r);
|
|
182
|
+
let sBytes = new Uint8Array(parsedSignature.s);
|
|
183
|
+
|
|
184
|
+
if (shouldRemoveLeadingZero(rBytes)) {
|
|
185
|
+
rBytes = rBytes.slice(1);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (shouldRemoveLeadingZero(sBytes)) {
|
|
189
|
+
sBytes = sBytes.slice(1);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
r: rBytes,
|
|
194
|
+
s: normalizeS(sBytes),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Normalizes the 's' value of an ECDSA signature to prevent signature malleability.
|
|
200
|
+
*
|
|
201
|
+
* @param {Uint8Array} sBuf - The 's' value of the signature as a Uint8Array.
|
|
202
|
+
* @returns {Uint8Array} The normalized 's' value as a Uint8Array.
|
|
203
|
+
*
|
|
204
|
+
* @description
|
|
205
|
+
* This function implements the process of normalizing the 's' value in an ECDSA signature.
|
|
206
|
+
* It ensures that the 's' value is always in the lower half of the curve's order,
|
|
207
|
+
* which helps prevent signature malleability attacks.
|
|
208
|
+
*
|
|
209
|
+
* The function uses the curve order 'n' for secp256k1:
|
|
210
|
+
* n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
|
|
211
|
+
*
|
|
212
|
+
* If 's' is greater than half of 'n', it is subtracted from 'n' to get the lower value.
|
|
213
|
+
*/
|
|
214
|
+
export function normalizeS(sBuf: Uint8Array): Uint8Array {
|
|
215
|
+
const n = BigInt("0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
|
|
216
|
+
const halfN = n / BigInt(2);
|
|
217
|
+
const sNumber: bigint = bufToBigint(sBuf);
|
|
218
|
+
|
|
219
|
+
if (sNumber / halfN) {
|
|
220
|
+
return new Uint8Array(bigintToBuf(n - sNumber));
|
|
221
|
+
} else {
|
|
222
|
+
return sBuf;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Determine if the DER-specific `00` byte at the start of an ECDSA signature byte sequence
|
|
228
|
+
* should be removed based on the following logic:
|
|
229
|
+
*
|
|
230
|
+
* "If the leading byte is 0x0, and the the high order bit on the second byte is not set to 0,
|
|
231
|
+
* then remove the leading 0x0 byte"
|
|
232
|
+
*/
|
|
233
|
+
function shouldRemoveLeadingZero(bytes: Uint8Array): boolean {
|
|
234
|
+
return bytes[0] === 0x0 && (bytes[1] & (1 << 7)) !== 0;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Decode from a Base64URL-encoded string to an ArrayBuffer. Best used when converting a
|
|
239
|
+
* credential ID from a JSON string to an ArrayBuffer, like in allowCredentials or
|
|
240
|
+
* excludeCredentials.
|
|
241
|
+
*
|
|
242
|
+
* @param buffer Value to decode from base64
|
|
243
|
+
* @param to (optional) The decoding to use, in case it's desirable to decode from base64 instead
|
|
244
|
+
*/
|
|
245
|
+
export function base64UrlToUint8Array(base64urlString: string, isUrl: boolean = true): Uint8Array {
|
|
246
|
+
const _buffer = toArrayBuffer(base64urlString, isUrl);
|
|
247
|
+
return new Uint8Array(_buffer);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function toArrayBuffer(data: string, isUrl: boolean) {
|
|
251
|
+
const
|
|
252
|
+
// Regular base64 characters
|
|
253
|
+
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
|
|
254
|
+
|
|
255
|
+
// Base64url characters
|
|
256
|
+
charsUrl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
|
|
257
|
+
|
|
258
|
+
genLookup = (target: string) => {
|
|
259
|
+
const lookupTemp = typeof Uint8Array === "undefined" ? [] : new Uint8Array(256);
|
|
260
|
+
const len = chars.length;
|
|
261
|
+
for (let i = 0; i < len; i++) {
|
|
262
|
+
lookupTemp[target.charCodeAt(i)] = i;
|
|
263
|
+
}
|
|
264
|
+
return lookupTemp;
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
// Use a lookup table to find the index.
|
|
268
|
+
lookup = genLookup(chars),
|
|
269
|
+
lookupUrl = genLookup(charsUrl);
|
|
270
|
+
|
|
271
|
+
const
|
|
272
|
+
len = data.length;
|
|
273
|
+
let bufferLength = data.length * 0.75,
|
|
274
|
+
i,
|
|
275
|
+
p = 0,
|
|
276
|
+
encoded1,
|
|
277
|
+
encoded2,
|
|
278
|
+
encoded3,
|
|
279
|
+
encoded4;
|
|
280
|
+
|
|
281
|
+
if (data[data.length - 1] === "=") {
|
|
282
|
+
bufferLength--;
|
|
283
|
+
if (data[data.length - 2] === "=") {
|
|
284
|
+
bufferLength--;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const
|
|
289
|
+
arraybuffer = new ArrayBuffer(bufferLength),
|
|
290
|
+
bytes = new Uint8Array(arraybuffer),
|
|
291
|
+
target = isUrl ? lookupUrl : lookup;
|
|
292
|
+
|
|
293
|
+
for (i = 0; i < len; i += 4) {
|
|
294
|
+
encoded1 = target[data.charCodeAt(i)];
|
|
295
|
+
encoded2 = target[data.charCodeAt(i + 1)];
|
|
296
|
+
encoded3 = target[data.charCodeAt(i + 2)];
|
|
297
|
+
encoded4 = target[data.charCodeAt(i + 3)];
|
|
298
|
+
|
|
299
|
+
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
|
|
300
|
+
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
|
|
301
|
+
bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return arraybuffer;
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
export function passkeyHashSignatureResponseFormat(
|
|
308
|
+
passkeyResponse: {
|
|
309
|
+
authenticatorData: string;
|
|
310
|
+
clientDataJSON: string;
|
|
311
|
+
signature: string;
|
|
312
|
+
},
|
|
313
|
+
contracts: {
|
|
314
|
+
passkey: Address;
|
|
315
|
+
},
|
|
316
|
+
) {
|
|
317
|
+
const signature = unwrapEC2Signature(base64UrlToUint8Array(passkeyResponse.signature));
|
|
318
|
+
const fatSignature = encodeAbiParameters(
|
|
319
|
+
[
|
|
320
|
+
{ type: "bytes" }, // authData
|
|
321
|
+
{ type: "bytes" }, // clientDataJson
|
|
322
|
+
{ type: "bytes32[2]" }, // signature (two elements)
|
|
323
|
+
],
|
|
324
|
+
[
|
|
325
|
+
toHex(base64UrlToUint8Array(passkeyResponse.authenticatorData)),
|
|
326
|
+
toHex(base64UrlToUint8Array(passkeyResponse.clientDataJSON)),
|
|
327
|
+
[toHex(signature.r), toHex(signature.s)],
|
|
328
|
+
],
|
|
329
|
+
);
|
|
330
|
+
const fullFormattedSig = encodeAbiParameters(
|
|
331
|
+
[
|
|
332
|
+
{ type: "bytes" }, // fat signature
|
|
333
|
+
{ type: "address" }, // validator address
|
|
334
|
+
{ type: "bytes[]" }, // validator data
|
|
335
|
+
],
|
|
336
|
+
[
|
|
337
|
+
fatSignature,
|
|
338
|
+
contracts.passkey,
|
|
339
|
+
["0x"], // FIXME: this is assuming there are no other hooks
|
|
340
|
+
],
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
return fullFormattedSig;
|
|
344
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { type Address, type Hash } from "viem";
|
|
2
|
+
|
|
3
|
+
export enum LimitType {
|
|
4
|
+
Unlimited = 0,
|
|
5
|
+
Lifetime = 1,
|
|
6
|
+
Allowance = 2,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Limit is the value tracked either for a lifetime or a period on-chain
|
|
11
|
+
* @member limitType - Used to validate limit & period values (unlimited has no limit, lifetime has no period, allowance has both!)
|
|
12
|
+
* @member limit - The limit is exceeded if the tracked value is greater than this over the provided period
|
|
13
|
+
* @member period - The block.timestamp divisor for the limit to be enforced (eg: 60 for a minute, 86400 for a day, 604800 for a week, unset for lifetime)
|
|
14
|
+
*/
|
|
15
|
+
export type Limit = {
|
|
16
|
+
limitType: LimitType;
|
|
17
|
+
limit: bigint;
|
|
18
|
+
period: bigint;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const LimitUnlimited = {
|
|
22
|
+
limitType: LimitType.Unlimited,
|
|
23
|
+
limit: 0n,
|
|
24
|
+
period: 0n,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const LimitZero = {
|
|
28
|
+
limitType: LimitType.Lifetime,
|
|
29
|
+
limit: 0n,
|
|
30
|
+
period: 0n,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Common logic operators to used combine multiple constraints
|
|
35
|
+
*/
|
|
36
|
+
export enum ConstraintCondition {
|
|
37
|
+
Unconstrained = 0,
|
|
38
|
+
Equal = 1,
|
|
39
|
+
Greater = 2,
|
|
40
|
+
Less = 3,
|
|
41
|
+
GreaterEqual = 4,
|
|
42
|
+
LessEqual = 5,
|
|
43
|
+
NotEqual = 6,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Constraint allows performing logic checks on any binary word (bytes32) in the transaction.
|
|
48
|
+
* This can let you set spend limits against functions on specific contracts
|
|
49
|
+
* @member index - The location of the start of the data in the transaction. This is not the index of the constraint within the containing array!
|
|
50
|
+
* @member condition - The kind of check to perform (None, =, >, <, >=, <=, !=)
|
|
51
|
+
* @member refValue - The value to compare against (as bytes32)
|
|
52
|
+
* @member limit - The limit to enforce on the parsed value (from index)
|
|
53
|
+
*/
|
|
54
|
+
export type Constraint = {
|
|
55
|
+
index: bigint;
|
|
56
|
+
condition: ConstraintCondition;
|
|
57
|
+
refValue: Hash;
|
|
58
|
+
limit: Limit;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* CallPolicy is a policy for a specific contract (address/function) call.
|
|
63
|
+
* @member target - Only one policy per target per session (unique mapping)
|
|
64
|
+
* @member selector - Solidity function selector (the selector directly), also unique mapping with target
|
|
65
|
+
* @member maxValuePerUse - Will reject transaction if value is set above this amount (for transfer or call)
|
|
66
|
+
* @member valueLimit - If not set, unlimited. If a number or a limit without a period, converts to a lifetime value. Also rejects transactions that have cumulative value greater than what's set here
|
|
67
|
+
* @member constraints - Array of conditions with specific limits for performing range and logic checks (e.g. 5 > x >= 30) on the transaction data (not value!)
|
|
68
|
+
*/
|
|
69
|
+
export type CallPolicy = {
|
|
70
|
+
target: Address;
|
|
71
|
+
valueLimit: Limit;
|
|
72
|
+
maxValuePerUse: bigint;
|
|
73
|
+
selector: Hash;
|
|
74
|
+
constraints: Constraint[];
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Simplified CallPolicy for transactions with less than 4 bytes of data
|
|
79
|
+
* @member target - Only one policy per target per session (unique mapping from CallPolicies)
|
|
80
|
+
* @member maxValuePerUse - Will reject transaction if value is set above this amount
|
|
81
|
+
* @member valueLimit - Validated from value
|
|
82
|
+
*/
|
|
83
|
+
export type TransferPolicy = {
|
|
84
|
+
target: Address;
|
|
85
|
+
maxValuePerUse: bigint;
|
|
86
|
+
valueLimit: Limit;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* SessionConfig is a set of policies and metadata to validate a transaction
|
|
91
|
+
* @member signer - The address that signs the transaction (session public key)
|
|
92
|
+
* @member expiresAt - The block.timestamp at which the session is no longer valid
|
|
93
|
+
* @member feeLimit - The maximum fee that can be paid for the transaction (maxFeePerGas * gasLimit)
|
|
94
|
+
* @member callPolicies - Used to validate the transaction data, has complex calldata parsing logic
|
|
95
|
+
* @member transferPolicies - Used to validate the transaction value when there's no additional data
|
|
96
|
+
*/
|
|
97
|
+
export type SessionConfig = {
|
|
98
|
+
signer: Address;
|
|
99
|
+
expiresAt: bigint;
|
|
100
|
+
feeLimit: Limit;
|
|
101
|
+
callPolicies: CallPolicy[];
|
|
102
|
+
transferPolicies: TransferPolicy[];
|
|
103
|
+
};
|