zksync-sso 0.0.0-beta.2 → 0.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +25 -34
  2. package/dist/_cjs/client/clients/passkey.js +1 -1
  3. package/dist/_cjs/client/clients/passkey.js.map +1 -1
  4. package/dist/_cjs/client/clients/session.js +1 -1
  5. package/dist/_cjs/client/clients/session.js.map +1 -1
  6. package/dist/_cjs/client-auth-server/index.js +1 -1
  7. package/dist/_cjs/client-auth-server/index.js.map +1 -1
  8. package/dist/_cjs/client-auth-server/session/index.js +146 -0
  9. package/dist/_cjs/client-auth-server/session/index.js.map +1 -0
  10. package/dist/_cjs/client-auth-server/session/type-utils.js +3 -0
  11. package/dist/_cjs/client-auth-server/session/type-utils.js.map +1 -0
  12. package/dist/_cjs/client-auth-server/session/utils.js +112 -0
  13. package/dist/_cjs/client-auth-server/session/utils.js.map +1 -0
  14. package/dist/_cjs/connector/index.js +21 -1
  15. package/dist/_cjs/connector/index.js.map +1 -1
  16. package/dist/_esm/client/clients/passkey.js +1 -1
  17. package/dist/_esm/client/clients/passkey.js.map +1 -1
  18. package/dist/_esm/client/clients/session.js +1 -1
  19. package/dist/_esm/client/clients/session.js.map +1 -1
  20. package/dist/_esm/client-auth-server/index.js +1 -1
  21. package/dist/_esm/client-auth-server/index.js.map +1 -1
  22. package/dist/_esm/client-auth-server/session/index.js +145 -0
  23. package/dist/_esm/client-auth-server/session/index.js.map +1 -0
  24. package/dist/_esm/client-auth-server/session/type-utils.js +2 -0
  25. package/dist/_esm/client-auth-server/session/type-utils.js.map +1 -0
  26. package/dist/_esm/client-auth-server/session/utils.js +108 -0
  27. package/dist/_esm/client-auth-server/session/utils.js.map +1 -0
  28. package/dist/_esm/connector/index.js +17 -1
  29. package/dist/_esm/connector/index.js.map +1 -1
  30. package/dist/_types/client-auth-server/Signer.d.ts +1 -1
  31. package/dist/_types/client-auth-server/Signer.d.ts.map +1 -1
  32. package/dist/_types/client-auth-server/WalletProvider.d.ts +1 -1
  33. package/dist/_types/client-auth-server/WalletProvider.d.ts.map +1 -1
  34. package/dist/_types/client-auth-server/index.d.ts +1 -1
  35. package/dist/_types/client-auth-server/index.d.ts.map +1 -1
  36. package/dist/_types/client-auth-server/rpc.d.ts +1 -1
  37. package/dist/_types/client-auth-server/rpc.d.ts.map +1 -1
  38. package/dist/_types/client-auth-server/session/index.d.ts +56 -0
  39. package/dist/_types/client-auth-server/session/index.d.ts.map +1 -0
  40. package/dist/_types/client-auth-server/session/type-utils.d.ts +12 -0
  41. package/dist/_types/client-auth-server/session/type-utils.d.ts.map +1 -0
  42. package/dist/_types/client-auth-server/session/utils.d.ts +7 -0
  43. package/dist/_types/client-auth-server/session/utils.d.ts.map +1 -0
  44. package/dist/_types/connector/index.d.ts +11 -0
  45. package/dist/_types/connector/index.d.ts.map +1 -1
  46. package/dist/_types/index.d.ts +1 -1
  47. package/dist/_types/index.d.ts.map +1 -1
  48. package/package.json +4 -2
  49. package/src/client/clients/passkey.ts +1 -1
  50. package/src/client/clients/session.ts +1 -1
  51. package/src/client-auth-server/Signer.ts +1 -1
  52. package/src/client-auth-server/WalletProvider.ts +1 -1
  53. package/src/client-auth-server/index.ts +1 -1
  54. package/src/client-auth-server/rpc.ts +1 -1
  55. package/src/client-auth-server/session/index.ts +223 -0
  56. package/src/client-auth-server/session/type-utils.ts +14 -0
  57. package/src/client-auth-server/session/utils.ts +117 -0
  58. package/src/connector/index.ts +50 -0
  59. package/src/index.ts +1 -1
  60. package/tsconfig.base.json +1 -1
  61. package/dist/_cjs/client-auth-server/session.js +0 -90
  62. package/dist/_cjs/client-auth-server/session.js.map +0 -1
  63. package/dist/_esm/client-auth-server/session.js +0 -91
  64. package/dist/_esm/client-auth-server/session.js.map +0 -1
  65. package/dist/_types/client-auth-server/session.d.ts +0 -45
  66. package/dist/_types/client-auth-server/session.d.ts.map +0 -1
  67. package/src/client-auth-server/session.ts +0 -139
@@ -6,7 +6,7 @@ import { type SessionConfig } from "../utils/session.js";
6
6
  import { StorageItem } from "../utils/storage.js";
7
7
  import type { AppMetadata, RequestArguments } from "./interface.js";
8
8
  import type { AuthServerRpcSchema, ExtractParams, ExtractReturnType, Method, RPCRequestMessage, RPCResponseMessage, RpcSchema } from "./rpc.js";
9
- import type { SessionPreferences } from "./session.js";
9
+ import type { SessionPreferences } from "./session/index.js";
10
10
 
11
11
  type Account = {
12
12
  address: Address;
@@ -11,7 +11,7 @@ import type {
11
11
  RequestArguments,
12
12
  } from "./interface.js";
13
13
  import { type ExtractReturnType, type Method } from "./rpc.js";
14
- import type { SessionPreferences } from "./session.js";
14
+ import type { SessionPreferences } from "./session/index.js";
15
15
  import { Signer } from "./Signer.js";
16
16
 
17
17
  const DEFAULT_AUTH_SERVER_URL = "https://auth-test.zksync.dev/confirm";
@@ -1,3 +1,3 @@
1
1
  export * from "./interface.js";
2
2
  export * from "./rpc.js";
3
- export * from "./session.js";
3
+ export * from "./session/index.js";
@@ -5,7 +5,7 @@ import type { Message } from "../communicator/index.js";
5
5
  import type { SerializedEthereumRpcError } from "../errors/index.js";
6
6
  import type { SessionConfig } from "../utils/session.js";
7
7
  import type { AppMetadata, RequestArguments } from "./interface.js";
8
- import type { SessionPreferences } from "./session.js";
8
+ import type { SessionPreferences } from "./session/index.js";
9
9
 
10
10
  export type AuthServerRpcSchema = [
11
11
  {
@@ -0,0 +1,223 @@
1
+ import { type Abi, type AbiFunction, type AbiStateMutability, type Address, type ContractFunctionArgs, type ContractFunctionName, encodeAbiParameters, getAddress, toFunctionSelector, toHex } from "viem";
2
+
3
+ import { ConstraintCondition, type Limit, LimitType, LimitUnlimited, LimitZero, type SessionConfig } from "../../utils/session.js";
4
+ import type { ContractWriteMutability, IndexedValues } from "./type-utils.js";
5
+ import { encodedInputToAbiChunks, getParameterChunkIndex, isDynamicInputType, isFollowedByDynamicInputType, msStringToSeconds } from "./utils.js";
6
+
7
+ export type PartialLimit = bigint | {
8
+ limit: bigint;
9
+ period?: string | bigint;
10
+ } | {
11
+ limitType: "lifetime" | LimitType.Lifetime;
12
+ limit: bigint;
13
+ } | {
14
+ limitType: "unlimited" | LimitType.Unlimited;
15
+ } | {
16
+ limitType: "allowance" | LimitType.Allowance;
17
+ limit: bigint;
18
+ period: string | bigint;
19
+ };
20
+
21
+ export type PartialCallPolicy = {
22
+ address: Address;
23
+ abi: Abi;
24
+ functionName: string;
25
+ maxValuePerUse?: bigint;
26
+ valueLimit?: PartialLimit;
27
+ constraints?: {
28
+ index: number;
29
+ value?: unknown;
30
+ condition?: keyof typeof ConstraintCondition;
31
+ limit?: PartialLimit;
32
+ }[];
33
+ };
34
+
35
+ export interface TypesafePartialCallPolicy<
36
+ abi extends Abi,
37
+ functionName extends ContractFunctionName<abi, ContractWriteMutability>,
38
+ > extends PartialCallPolicy {
39
+ abi: abi;
40
+ functionName: functionName;
41
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
42
+ // @ts-ignore
43
+ constraints?: (IndexedValues<ContractFunctionArgs<abi, ContractWriteMutability, functionName>>[number] & {
44
+ condition?: keyof typeof ConstraintCondition;
45
+ limit?: PartialLimit;
46
+ })[];
47
+ };
48
+
49
+ // Typesafety helper function
50
+ export const callPolicy = <
51
+ abi extends Abi,
52
+ functionName extends ContractFunctionName<abi, ContractWriteMutability>,
53
+ >(
54
+ policy: TypesafePartialCallPolicy<abi, functionName>,
55
+ ): PartialCallPolicy => policy as PartialCallPolicy;
56
+
57
+ export type PartialTransferPolicy = {
58
+ to: Address;
59
+ maxValuePerUse?: bigint;
60
+ valueLimit?: PartialLimit;
61
+ };
62
+
63
+ export interface SessionPreferences {
64
+ expiry?: string | bigint | Date;
65
+ feeLimit?: PartialLimit;
66
+ contractCalls?: PartialCallPolicy[];
67
+ transfers?: PartialTransferPolicy[];
68
+ };
69
+
70
+ export const formatLimitPreferences = (limit: PartialLimit): Limit => {
71
+ /* Just bigint was passed */
72
+ if (typeof limit === "bigint") {
73
+ return {
74
+ limitType: LimitType.Lifetime,
75
+ limit,
76
+ period: 0n,
77
+ };
78
+ }
79
+
80
+ /* LimitType was specified */
81
+ if ("limitType" in limit) {
82
+ if (limit.limitType === "lifetime" || limit.limitType === LimitType.Lifetime) {
83
+ return {
84
+ limitType: LimitType.Lifetime,
85
+ limit: limit.limit,
86
+ period: 0n,
87
+ };
88
+ } else if (limit.limitType === "unlimited" || limit.limitType === LimitType.Unlimited) {
89
+ return {
90
+ limitType: LimitType.Unlimited,
91
+ limit: 0n,
92
+ period: 0n,
93
+ };
94
+ } else if (limit.limitType === "allowance" || limit.limitType === LimitType.Allowance) {
95
+ return {
96
+ limitType: LimitType.Allowance,
97
+ limit: limit.limit,
98
+ period: typeof limit.period === "string" ? msStringToSeconds(limit.period) : limit.period,
99
+ };
100
+ }
101
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
102
+ throw new Error(`Invalid limit type: ${(limit as any).limitType}`);
103
+ }
104
+
105
+ /* LimitType not selected */
106
+ if (limit.period) {
107
+ return {
108
+ limitType: LimitType.Allowance,
109
+ limit: limit.limit,
110
+ period: typeof limit.period === "string" ? msStringToSeconds(limit.period) : limit.period,
111
+ };
112
+ }
113
+ return {
114
+ limitType: LimitType.Lifetime,
115
+ limit: limit.limit,
116
+ period: 0n,
117
+ };
118
+ };
119
+
120
+ export const formatDatePreferences = (date: string | bigint | Date): bigint => {
121
+ if (typeof date === "string") {
122
+ const now = Math.floor(new Date().getTime() / 1000);
123
+ const seconds = msStringToSeconds(date);
124
+ return BigInt(now) + seconds;
125
+ }
126
+ if (date instanceof Date) {
127
+ const seconds = Math.floor(date.getTime() / 1000);
128
+ return BigInt(seconds);
129
+ }
130
+ return date;
131
+ };
132
+
133
+ export function formatSessionPreferences(
134
+ preferences: SessionPreferences,
135
+ defaults: {
136
+ expiresAt: bigint;
137
+ feeLimit: Limit;
138
+ },
139
+ ): Omit<SessionConfig, "signer"> {
140
+ return {
141
+ expiresAt: preferences.expiry ? formatDatePreferences(preferences.expiry) : defaults.expiresAt,
142
+ feeLimit: preferences.feeLimit ? formatLimitPreferences(preferences.feeLimit) : defaults.feeLimit,
143
+ callPolicies: preferences.contractCalls?.map((policy) => {
144
+ const allowedStateMutability: ContractWriteMutability[] = ["nonpayable", "payable"];
145
+ const abiFunction = (policy.abi as Abi).find((fn) => fn.type === "function" && fn.name === policy.functionName && (allowedStateMutability as AbiStateMutability[]).includes(fn.stateMutability)) as AbiFunction;
146
+ if (!abiFunction) throw new Error(`Function not found in the provided ABI: ${policy.functionName}`);
147
+
148
+ const selector = toFunctionSelector(abiFunction);
149
+ const valueLimit = policy.valueLimit ? formatLimitPreferences(policy.valueLimit) : LimitZero;
150
+
151
+ return {
152
+ target: getAddress(policy.address.toLowerCase()),
153
+ maxValuePerUse: policy.maxValuePerUse ?? valueLimit.limit,
154
+ valueLimit,
155
+ selector: selector,
156
+ constraints: policy.constraints?.map((constraint) => {
157
+ const limit = constraint.limit ? formatLimitPreferences(constraint.limit) : LimitUnlimited;
158
+ const condition = constraint.condition ? ConstraintCondition[constraint.condition] : ConstraintCondition.Unconstrained;
159
+
160
+ const input = abiFunction.inputs[constraint.index];
161
+ if (!input) {
162
+ throw new Error(`Target function parameter not found in the provided ABI function. Provided at function ${policy.functionName}, index ${constraint.index}`);
163
+ }
164
+
165
+ const isDynamicType = isDynamicInputType(input.type);
166
+ if (isDynamicType) {
167
+ throw new Error(`Function parameters with dynamic types are not supported for constraint validation. Provided at function ${policy.functionName}, index ${constraint.index}`);
168
+ }
169
+
170
+ const isFollowedByDynamicType = isFollowedByDynamicInputType(abiFunction, constraint.index);
171
+ if (isFollowedByDynamicType) {
172
+ throw new Error(`Target function parameter is followed by a dynamic type parameter. Provided at function ${policy.functionName}, index ${constraint.index}`);
173
+ }
174
+
175
+ const startingAbiChunkIndex = getParameterChunkIndex(abiFunction, constraint.index);
176
+ if (constraint.value === undefined || constraint.value === null) {
177
+ return {
178
+ index: BigInt(startingAbiChunkIndex),
179
+ condition: ConstraintCondition.Unconstrained,
180
+ refValue: toHex("", { size: 32 }),
181
+ limit,
182
+ };
183
+ }
184
+
185
+ const encodedInput = encodeAbiParameters([input], [constraint.value]);
186
+ const abiBytesChunks = encodedInputToAbiChunks(encodedInput);
187
+ const ALLOWED_OVERFLOW_CONDITIONS: ConstraintCondition[] = [
188
+ ConstraintCondition.Unconstrained,
189
+ ConstraintCondition.Equal,
190
+ ConstraintCondition.NotEqual,
191
+ ];
192
+ const ALLOWED_OVERFLOW_LIMIT_TYPES: LimitType[] = [
193
+ LimitType.Unlimited,
194
+ ];
195
+
196
+ if (
197
+ abiBytesChunks.length > 1
198
+ && !ALLOWED_OVERFLOW_CONDITIONS.includes(condition)
199
+ && !ALLOWED_OVERFLOW_LIMIT_TYPES.includes(limit.limitType)
200
+ ) {
201
+ /* Can't make validation for < > when value is split across multiple chunks */
202
+ throw new Error(`Encoded input size of parameter at index ${constraint.index} of ${policy.functionName} exceeds the maximum size of 32 bytes: ${abiBytesChunks.length * 32} bytes`);
203
+ };
204
+
205
+ return abiBytesChunks.map((abiChunk, index) => ({
206
+ index: BigInt(startingAbiChunkIndex + index),
207
+ condition,
208
+ refValue: abiChunk,
209
+ limit,
210
+ }));
211
+ }).flat() ?? [],
212
+ };
213
+ }) ?? [],
214
+ transferPolicies: preferences.transfers?.map((policy) => {
215
+ const valueLimit = policy.valueLimit ? formatLimitPreferences(policy.valueLimit) : LimitZero;
216
+ return {
217
+ target: getAddress(policy.to.toLowerCase()),
218
+ maxValuePerUse: policy.maxValuePerUse ?? valueLimit.limit,
219
+ valueLimit,
220
+ };
221
+ }) ?? [],
222
+ };
223
+ }
@@ -0,0 +1,14 @@
1
+ import { type AbiStateMutability } from "viem";
2
+
3
+ // Helper type to convert string indices to numeric indices
4
+ type ToNumber<S extends string> = S extends `${infer N extends number}` ? N : never;
5
+
6
+ // Extract numeric keys as strings
7
+ type NumericKeys<T extends unknown[]> = Extract<keyof T, `${number}`>;
8
+
9
+ // Updated IndexedValues type with numeric indices
10
+ export type IndexedValues<T extends unknown[]> = Array<{
11
+ [K in NumericKeys<T>]: { index: ToNumber<K>; value?: T[K] };
12
+ }[NumericKeys<T>]>;
13
+
14
+ export type ContractWriteMutability = Extract<AbiStateMutability, "nonpayable" | "payable">;
@@ -0,0 +1,117 @@
1
+ import ms from "ms";
2
+ import { type AbiFunction, type AbiParameter, type Address, encodeAbiParameters, type Hash, toHex } from "viem";
3
+
4
+ const DYNAMIC_ABI_INPUT_TYPES = ["bytes", "string"];
5
+
6
+ export const isDynamicInputType = (inputType: string) => {
7
+ return inputType.endsWith("[]") || DYNAMIC_ABI_INPUT_TYPES.includes(inputType);
8
+ };
9
+
10
+ const includesDynamicInputType = (abiParameters: readonly AbiParameter[]): boolean => {
11
+ return abiParameters.some((input) => {
12
+ const isDynamicType = isDynamicInputType(input.type);
13
+ if (isDynamicType) return true;
14
+
15
+ if (input.type.startsWith("tuple")) {
16
+ const components = (input as TupleAbiParameter).components;
17
+ if (!components) throw new Error("Tuple without components is unsupported");
18
+ return includesDynamicInputType(components);
19
+ }
20
+ return false;
21
+ });
22
+ };
23
+
24
+ export const isFollowedByDynamicInputType = (abiFunction: AbiFunction, targetInputIndex: number) => {
25
+ if (targetInputIndex >= abiFunction.inputs.length) {
26
+ throw new Error(`Input index ${targetInputIndex} is out of bounds`);
27
+ }
28
+
29
+ return includesDynamicInputType(abiFunction.inputs.slice(0, targetInputIndex));
30
+ };
31
+
32
+ export const encodedInputToAbiChunks = (encodedInput: string) => {
33
+ if (!encodedInput.startsWith("0x")) {
34
+ throw new Error("Input is not a valid hex string");
35
+ }
36
+ return (encodedInput.slice(2).match(/.{1,64}/g) || []) as Hash[]; // 32 bytes abi chunks
37
+ };
38
+
39
+ const getDummyBytesValue = (type: string) => {
40
+ const size = parseInt(type.slice(5)) || 32;
41
+ return toHex("", { size });
42
+ };
43
+
44
+ // Function to generate dummy values for ABI types
45
+ const getDummyValue = (type: string) => {
46
+ if (type === "address") return "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049" as Address;
47
+ if (type.startsWith("uint") || type.startsWith("int")) return 0n; // BigInt for numbers
48
+ if (type.startsWith("bytes")) return getDummyBytesValue(type); // Empty bytes
49
+ if (type === "bool") return false;
50
+ if (type === "string") return ""; // Empty string
51
+ throw new Error(`Unsupported ABI type: ${type}`);
52
+ };
53
+
54
+ function getArrayComponents(
55
+ type: string,
56
+ ): [length: number | null, innerType: string] | undefined {
57
+ const matches = type.match(/^(.*)\[(\d+)?\]$/);
58
+ return matches
59
+ ? [matches[2] ? Number(matches[2]) : null, matches[1]]
60
+ : undefined;
61
+ }
62
+
63
+ type TupleAbiParameter = AbiParameter & { components: readonly AbiParameter[] };
64
+
65
+ // Recursive function to fill dummy values for complex types like tuples
66
+ const getDummyValues = (inputs: readonly AbiParameter[]): unknown[] => {
67
+ return inputs.map((input) => {
68
+ const arrayComponents = getArrayComponents(input.type);
69
+ if (arrayComponents) {
70
+ // Recursively fill array components
71
+ const [length, innerType] = arrayComponents;
72
+ if (!length) throw new Error("Dynamic array length is unsupported");
73
+ const arrayValue = Array.from({ length }, () => getDummyValues([{
74
+ ...input,
75
+ type: innerType,
76
+ }]));
77
+ return arrayValue;
78
+ }
79
+ if (input.type.startsWith("tuple")) {
80
+ // Recursively fill tuple components
81
+ const components = (input as TupleAbiParameter).components;
82
+ if (!components) throw new Error("Tuple without components is unsupported");
83
+ return getDummyValues(components);
84
+ }
85
+ return getDummyValue(input.type);
86
+ });
87
+ };
88
+
89
+ export const getParameterChunkIndex = (
90
+ abiFunction: AbiFunction,
91
+ targetInputIndex: number,
92
+ ): number => {
93
+ if (targetInputIndex >= abiFunction.inputs.length) {
94
+ throw new Error(`Input index ${targetInputIndex} is out of bounds`);
95
+ }
96
+
97
+ const inputs = abiFunction.inputs.slice(0, targetInputIndex);
98
+ const dummyValues = getDummyValues(inputs);
99
+ const encoded = encodeAbiParameters(inputs, dummyValues);
100
+ const chunks = encodedInputToAbiChunks(encoded);
101
+ const chunkIndex = chunks.length;
102
+
103
+ return chunkIndex;
104
+ };
105
+
106
+ export const msStringToSeconds = (value: string): bigint => {
107
+ let millis: number;
108
+ try {
109
+ millis = ms(value);
110
+ } catch (error) {
111
+ throw new Error(`Invalid date format: ${value}: ${error}`);
112
+ }
113
+ if (millis < 0) throw new Error(`Date can't be in the past: ${value}`);
114
+ if (millis === 0) throw new Error(`Date can't be zero: ${value}`);
115
+ const seconds = Math.floor(millis / 1000);
116
+ return BigInt(seconds);
117
+ };
@@ -1,17 +1,25 @@
1
1
  import {
2
2
  ChainNotConfiguredError,
3
+ type Config,
3
4
  type Connector,
4
5
  createConnector,
6
+ getConnectorClient as wagmiGetConnectorClient,
7
+ type GetConnectorClientParameters,
5
8
  } from "@wagmi/core";
9
+ import type { Compute } from "@wagmi/core/internal";
6
10
  import {
11
+ type Account,
12
+ type Client,
7
13
  getAddress,
8
14
  SwitchChainError,
9
15
  toHex,
10
16
  UserRejectedRequestError,
11
17
  } from "viem";
12
18
 
19
+ import type { ZksyncSsoSessionClient } from "../client/index.js";
13
20
  import { EthereumProviderError } from "../errors/errors.js";
14
21
  import { type AppMetadata, type ProviderInterface, type SessionPreferences, WalletProvider } from "../index.js";
22
+ export { callPolicy } from "../client-auth-server/index.js";
15
23
 
16
24
  export type ZksyncSsoConnectorOptions = {
17
25
  metadata?: Partial<AppMetadata>;
@@ -175,3 +183,45 @@ export const zksyncSsoConnector = (parameters: ZksyncSsoConnectorOptions) => {
175
183
  },
176
184
  }));
177
185
  };
186
+
187
+ export type GetConnectedSsoClientReturnType<
188
+ config extends Config = Config,
189
+ chainId extends config["chains"][number]["id"] = config["chains"][number]["id"],
190
+ > = Compute<
191
+ ZksyncSsoSessionClient<
192
+ config["_internal"]["transports"][chainId],
193
+ Extract<config["chains"][number], { id: chainId }>,
194
+ undefined,
195
+ Account
196
+ >
197
+ >;
198
+
199
+ export const isSsoSessionClient = (client: Client): boolean => {
200
+ return client.key === "zksync-sso-session-wallet";
201
+ };
202
+
203
+ export const isSsoSessionClientConnected = async<
204
+ config extends Config,
205
+ chainId extends config["chains"][number]["id"],
206
+ >(
207
+ config: config,
208
+ parameters: GetConnectorClientParameters<config, chainId> = {},
209
+ ): Promise<boolean> => {
210
+ const connectorClient = await wagmiGetConnectorClient(config, parameters);
211
+ return isSsoSessionClient(connectorClient);
212
+ };
213
+
214
+ export const getConnectedSsoClient = async<
215
+ config extends Config,
216
+ chainId extends config["chains"][number]["id"],
217
+ >(
218
+ config: config,
219
+ parameters: GetConnectorClientParameters<config, chainId> = {},
220
+ ): Promise<GetConnectedSsoClientReturnType<config, chainId>> => {
221
+ const connectorClient = await wagmiGetConnectorClient(config, parameters);
222
+ if (!isSsoSessionClient(connectorClient)) {
223
+ throw new Error("ZKsync SSO Session Client not connected");
224
+ }
225
+ const sessionClient = connectorClient as unknown as GetConnectedSsoClientReturnType<config, chainId>;
226
+ return sessionClient;
227
+ };
package/src/index.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export type { AppMetadata, ProviderInterface } from "./client-auth-server/interface.js";
2
- export type { SessionPreferences } from "./client-auth-server/session.js";
2
+ export type { SessionPreferences } from "./client-auth-server/session/index.js";
3
3
  export { WalletProvider, type WalletProviderConstructorOptions } from "./client-auth-server/WalletProvider.js";
@@ -25,7 +25,7 @@
25
25
 
26
26
  // Interop constraints
27
27
  "esModuleInterop": false,
28
- "allowSyntheticDefaultImports": false,
28
+ "allowSyntheticDefaultImports": true,
29
29
  "forceConsistentCasingInFileNames": true,
30
30
  "verbatimModuleSyntax": true,
31
31
 
@@ -1,90 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.formatSessionPreferences = formatSessionPreferences;
4
- const viem_1 = require("viem");
5
- const session_js_1 = require("../utils/session.js");
6
- ;
7
- const formatLimitPreferences = (limit) => {
8
- if (typeof limit === "bigint") {
9
- return {
10
- limitType: session_js_1.LimitType.Lifetime,
11
- limit,
12
- period: 0n,
13
- };
14
- }
15
- if ("limitType" in limit) {
16
- if (limit.limitType === "lifetime" || limit.limitType === session_js_1.LimitType.Lifetime) {
17
- return {
18
- limitType: session_js_1.LimitType.Lifetime,
19
- limit: limit.limit,
20
- period: 0n,
21
- };
22
- }
23
- else if (limit.limitType === "unlimited" || limit.limitType === session_js_1.LimitType.Unlimited) {
24
- return {
25
- limitType: session_js_1.LimitType.Unlimited,
26
- limit: 0n,
27
- period: 0n,
28
- };
29
- }
30
- else if (limit.limitType === "allowance" || limit.limitType === session_js_1.LimitType.Allowance) {
31
- return {
32
- limitType: session_js_1.LimitType.Allowance,
33
- limit: limit.limit,
34
- period: limit.period,
35
- };
36
- }
37
- throw new Error(`Invalid limit type: ${limit.limitType}`);
38
- }
39
- if (!limit.period) {
40
- return {
41
- limitType: session_js_1.LimitType.Lifetime,
42
- limit: limit.limit,
43
- period: 0n,
44
- };
45
- }
46
- return {
47
- limitType: session_js_1.LimitType.Allowance,
48
- limit: limit.limit,
49
- period: limit.period,
50
- };
51
- };
52
- const formatDatePreferences = (date) => {
53
- if (date instanceof Date) {
54
- return BigInt(Math.floor(date.getTime() / 1000));
55
- }
56
- return date;
57
- };
58
- function formatSessionPreferences(preferences, defaults) {
59
- return {
60
- expiresAt: preferences.expiresAt ? formatDatePreferences(preferences.expiresAt) : defaults.expiresAt,
61
- feeLimit: preferences.feeLimit ? formatLimitPreferences(preferences.feeLimit) : defaults.feeLimit,
62
- callPolicies: preferences.contractCalls?.map((policy) => {
63
- const valueLimit = policy.valueLimit ? formatLimitPreferences(policy.valueLimit) : session_js_1.LimitZero;
64
- const selector = policy.function ? (0, viem_1.toFunctionSelector)(policy.function) : policy.selector;
65
- if (!selector)
66
- throw new Error("Missing function or selector in contract call policy");
67
- return {
68
- target: (0, viem_1.getAddress)(policy.address.toLowerCase()),
69
- maxValuePerUse: policy.maxValuePerUse ?? valueLimit.limit,
70
- valueLimit,
71
- selector: selector,
72
- constraints: policy.constraints?.map((constraint) => ({
73
- index: BigInt(constraint.index),
74
- condition: typeof constraint.condition == "string" ? session_js_1.ConstraintCondition[constraint.condition] : (constraint.condition ?? session_js_1.ConstraintCondition.Unconstrained),
75
- refValue: constraint.refValue ?? (0, viem_1.toHex)("", { size: 32 }),
76
- limit: constraint.limit ? formatLimitPreferences(constraint.limit) : session_js_1.LimitUnlimited,
77
- })) ?? [],
78
- };
79
- }) ?? [],
80
- transferPolicies: preferences.transfers?.map((policy) => {
81
- const valueLimit = policy.valueLimit ? formatLimitPreferences(policy.valueLimit) : session_js_1.LimitZero;
82
- return {
83
- target: (0, viem_1.getAddress)(policy.to.toLowerCase()),
84
- maxValuePerUse: policy.maxValuePerUse ?? valueLimit.limit,
85
- valueLimit,
86
- };
87
- }) ?? [],
88
- };
89
- }
90
- //# sourceMappingURL=session.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/client-auth-server/session.ts"],"names":[],"mappings":"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"}
@@ -1,91 +0,0 @@
1
- import { getAddress, toFunctionSelector, toHex } from "viem";
2
- import { ConstraintCondition, LimitType, LimitUnlimited, LimitZero } from "../utils/session.js";
3
- ;
4
- const formatLimitPreferences = (limit) => {
5
- /* Just bigint was passed */
6
- if (typeof limit === "bigint") {
7
- return {
8
- limitType: LimitType.Lifetime,
9
- limit,
10
- period: 0n,
11
- };
12
- }
13
- /* LimitType was specified */
14
- if ("limitType" in limit) {
15
- if (limit.limitType === "lifetime" || limit.limitType === LimitType.Lifetime) {
16
- return {
17
- limitType: LimitType.Lifetime,
18
- limit: limit.limit,
19
- period: 0n,
20
- };
21
- }
22
- else if (limit.limitType === "unlimited" || limit.limitType === LimitType.Unlimited) {
23
- return {
24
- limitType: LimitType.Unlimited,
25
- limit: 0n,
26
- period: 0n,
27
- };
28
- }
29
- else if (limit.limitType === "allowance" || limit.limitType === LimitType.Allowance) {
30
- return {
31
- limitType: LimitType.Allowance,
32
- limit: limit.limit,
33
- period: limit.period,
34
- };
35
- }
36
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
- throw new Error(`Invalid limit type: ${limit.limitType}`);
38
- }
39
- /* LimitType not selected */
40
- if (!limit.period) {
41
- return {
42
- limitType: LimitType.Lifetime,
43
- limit: limit.limit,
44
- period: 0n,
45
- };
46
- }
47
- return {
48
- limitType: LimitType.Allowance,
49
- limit: limit.limit,
50
- period: limit.period,
51
- };
52
- };
53
- const formatDatePreferences = (date) => {
54
- if (date instanceof Date) {
55
- return BigInt(Math.floor(date.getTime() / 1000));
56
- }
57
- return date;
58
- };
59
- export function formatSessionPreferences(preferences, defaults) {
60
- return {
61
- expiresAt: preferences.expiresAt ? formatDatePreferences(preferences.expiresAt) : defaults.expiresAt,
62
- feeLimit: preferences.feeLimit ? formatLimitPreferences(preferences.feeLimit) : defaults.feeLimit,
63
- callPolicies: preferences.contractCalls?.map((policy) => {
64
- const valueLimit = policy.valueLimit ? formatLimitPreferences(policy.valueLimit) : LimitZero;
65
- const selector = policy.function ? toFunctionSelector(policy.function) : policy.selector;
66
- if (!selector)
67
- throw new Error("Missing function or selector in contract call policy");
68
- return {
69
- target: getAddress(policy.address.toLowerCase()),
70
- maxValuePerUse: policy.maxValuePerUse ?? valueLimit.limit,
71
- valueLimit,
72
- selector: selector,
73
- constraints: policy.constraints?.map((constraint) => ({
74
- index: BigInt(constraint.index),
75
- condition: typeof constraint.condition == "string" ? ConstraintCondition[constraint.condition] : (constraint.condition ?? ConstraintCondition.Unconstrained),
76
- refValue: constraint.refValue ?? toHex("", { size: 32 }),
77
- limit: constraint.limit ? formatLimitPreferences(constraint.limit) : LimitUnlimited,
78
- })) ?? [],
79
- };
80
- }) ?? [],
81
- transferPolicies: preferences.transfers?.map((policy) => {
82
- const valueLimit = policy.valueLimit ? formatLimitPreferences(policy.valueLimit) : LimitZero;
83
- return {
84
- target: getAddress(policy.to.toLowerCase()),
85
- maxValuePerUse: policy.maxValuePerUse ?? valueLimit.limit,
86
- valueLimit,
87
- };
88
- }) ?? [],
89
- };
90
- }
91
- //# sourceMappingURL=session.js.map