@crossmint/client-sdk-smart-wallet 0.1.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.
Files changed (45) hide show
  1. package/LICENSE +201 -0
  2. package/dist/index.cjs +2 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +289 -0
  5. package/dist/index.d.ts +289 -0
  6. package/dist/index.js +2 -0
  7. package/dist/index.js.map +1 -0
  8. package/package.json +46 -0
  9. package/src/ABI/ERC1155.json +325 -0
  10. package/src/ABI/ERC20.json +222 -0
  11. package/src/ABI/ERC721.json +320 -0
  12. package/src/SmartWalletSDK.test.ts +32 -0
  13. package/src/SmartWalletSDK.ts +75 -0
  14. package/src/api/APIErrorService.ts +72 -0
  15. package/src/api/BaseCrossmintService.ts +82 -0
  16. package/src/api/CrossmintWalletService.test.ts +42 -0
  17. package/src/api/CrossmintWalletService.ts +50 -0
  18. package/src/blockchain/BlockchainNetworks.ts +121 -0
  19. package/src/blockchain/token/index.ts +1 -0
  20. package/src/blockchain/transfer.ts +54 -0
  21. package/src/blockchain/wallets/EVMSmartWallet.ts +109 -0
  22. package/src/blockchain/wallets/clientDecorator.ts +127 -0
  23. package/src/blockchain/wallets/eoa.ts +49 -0
  24. package/src/blockchain/wallets/index.ts +1 -0
  25. package/src/blockchain/wallets/passkey.ts +117 -0
  26. package/src/blockchain/wallets/paymaster.ts +49 -0
  27. package/src/blockchain/wallets/service.ts +193 -0
  28. package/src/error/index.ts +148 -0
  29. package/src/error/processor.ts +36 -0
  30. package/src/index.ts +34 -0
  31. package/src/services/logging/BrowserLoggerInterface.ts +5 -0
  32. package/src/services/logging/ConsoleProvider.ts +24 -0
  33. package/src/services/logging/DatadogProvider.ts +39 -0
  34. package/src/services/logging/index.ts +16 -0
  35. package/src/types/API.ts +40 -0
  36. package/src/types/Config.ts +35 -0
  37. package/src/types/Tokens.ts +27 -0
  38. package/src/types/internal.ts +50 -0
  39. package/src/utils/blockchain.ts +15 -0
  40. package/src/utils/constants.ts +31 -0
  41. package/src/utils/environment.ts +3 -0
  42. package/src/utils/helpers.ts +15 -0
  43. package/src/utils/log.test.ts +76 -0
  44. package/src/utils/log.ts +157 -0
  45. package/src/utils/signer.ts +36 -0
@@ -0,0 +1,193 @@
1
+ import { type SignerData, displayPasskey } from "@/types/API";
2
+ import { equalsIgnoreCase } from "@/utils/helpers";
3
+ import { type KernelSmartAccount, createKernelAccountClient } from "@zerodev/sdk";
4
+ import { ENTRYPOINT_ADDRESS_V06, ENTRYPOINT_ADDRESS_V07 } from "permissionless";
5
+ import type { EntryPoint } from "permissionless/types/entrypoint";
6
+ import { Address, type HttpTransport, createPublicClient, getAddress, http } from "viem";
7
+
8
+ import { blockchainToChainId } from "@crossmint/common-sdk-base";
9
+
10
+ import type { CrossmintWalletService, EVMBlockchainIncludingTestnet } from "../../api/CrossmintWalletService";
11
+ import {
12
+ AdminMismatchError,
13
+ CrossmintServiceError,
14
+ SmartWalletSDKError,
15
+ UserWalletAlreadyCreatedError,
16
+ } from "../../error";
17
+ import type { EntryPointDetails, UserParams, WalletParams } from "../../types/Config";
18
+ import {
19
+ SUPPORTED_ENTRYPOINT_VERSIONS,
20
+ SUPPORTED_KERNEL_VERSIONS,
21
+ SmartWalletClient,
22
+ type SupportedKernelVersion,
23
+ type WalletCreationParams,
24
+ isSupportedEntryPointVersion,
25
+ isSupportedKernelVersion,
26
+ } from "../../types/internal";
27
+ import { CURRENT_VERSION, ZERO_DEV_TYPE } from "../../utils/constants";
28
+ import { getBundlerRPC, getViemNetwork } from "../BlockchainNetworks";
29
+ import { EVMSmartWallet } from "./EVMSmartWallet";
30
+ import { ClientDecorator } from "./clientDecorator";
31
+ import { EOAAccountService, type EOAWalletParams } from "./eoa";
32
+ import { PasskeyAccountService, isPasskeyParams } from "./passkey";
33
+ import { paymasterMiddleware, usePaymaster } from "./paymaster";
34
+
35
+ export class SmartWalletService {
36
+ constructor(
37
+ private readonly crossmintWalletService: CrossmintWalletService,
38
+ private readonly clientDecorator: ClientDecorator,
39
+ private readonly accountFactory = new AccountFactory(
40
+ new EOAAccountService(),
41
+ new PasskeyAccountService(crossmintWalletService)
42
+ )
43
+ ) {}
44
+
45
+ public async getOrCreate(
46
+ user: UserParams,
47
+ chain: EVMBlockchainIncludingTestnet,
48
+ walletParams: WalletParams
49
+ ): Promise<EVMSmartWallet> {
50
+ const { entryPoint, kernelVersion, existingSignerConfig, smartContractWalletAddress, userId } =
51
+ await this.fetchConfig(user, chain);
52
+ const publicClient = createPublicClient({ transport: http(getBundlerRPC(chain)) });
53
+
54
+ const { account, signerData } = await this.accountFactory.get(
55
+ {
56
+ chain,
57
+ walletParams,
58
+ publicClient,
59
+ user: { ...user, id: userId },
60
+ entryPoint,
61
+ kernelVersion,
62
+ },
63
+ existingSignerConfig
64
+ );
65
+
66
+ if (smartContractWalletAddress != null && !equalsIgnoreCase(smartContractWalletAddress, account.address)) {
67
+ throw new UserWalletAlreadyCreatedError(userId);
68
+ }
69
+
70
+ if (existingSignerConfig == null) {
71
+ await this.crossmintWalletService.idempotentCreateSmartWallet(user, {
72
+ type: ZERO_DEV_TYPE,
73
+ smartContractWalletAddress: account.address,
74
+ signerData: signerData,
75
+ version: CURRENT_VERSION,
76
+ baseLayer: "evm",
77
+ chainId: blockchainToChainId(chain),
78
+ entryPointVersion: entryPoint.version,
79
+ kernelVersion,
80
+ });
81
+ }
82
+
83
+ const kernelAccountClient: SmartWalletClient = createKernelAccountClient({
84
+ account,
85
+ chain: getViemNetwork(chain),
86
+ entryPoint: account.entryPoint,
87
+ bundlerTransport: http(getBundlerRPC(chain)),
88
+ ...(usePaymaster(chain) && paymasterMiddleware({ entryPoint: account.entryPoint, chain })),
89
+ });
90
+
91
+ const smartAccountClient = this.clientDecorator.decorate({
92
+ crossmintChain: chain,
93
+ smartAccountClient: kernelAccountClient,
94
+ });
95
+
96
+ return new EVMSmartWallet(this.crossmintWalletService, smartAccountClient, publicClient, chain);
97
+ }
98
+
99
+ private async fetchConfig(
100
+ user: UserParams,
101
+ chain: EVMBlockchainIncludingTestnet
102
+ ): Promise<{
103
+ entryPoint: EntryPointDetails;
104
+ kernelVersion: SupportedKernelVersion;
105
+ userId: string;
106
+ existingSignerConfig?: SignerData;
107
+ smartContractWalletAddress?: Address;
108
+ }> {
109
+ const { entryPointVersion, kernelVersion, signers, smartContractWalletAddress, userId } =
110
+ await this.crossmintWalletService.getSmartWalletConfig(user, chain);
111
+
112
+ if (!isSupportedKernelVersion(kernelVersion)) {
113
+ throw new SmartWalletSDKError(
114
+ `Unsupported kernel version. Supported versions: ${SUPPORTED_KERNEL_VERSIONS.join(
115
+ ", "
116
+ )}. Version used: ${kernelVersion}, Please contact support`
117
+ );
118
+ }
119
+
120
+ if (!isSupportedEntryPointVersion(entryPointVersion)) {
121
+ throw new SmartWalletSDKError(
122
+ `Unsupported entry point version. Supported versions: ${SUPPORTED_ENTRYPOINT_VERSIONS.join(
123
+ ", "
124
+ )}. Version used: ${entryPointVersion}. Please contact support`
125
+ );
126
+ }
127
+
128
+ if (
129
+ (entryPointVersion === "v0.7" && kernelVersion.startsWith("0.2")) ||
130
+ (entryPointVersion === "v0.6" && kernelVersion.startsWith("0.3"))
131
+ ) {
132
+ throw new SmartWalletSDKError(
133
+ `Unsupported combination: entryPoint ${entryPointVersion} and kernel version ${kernelVersion}. Please contact support`
134
+ );
135
+ }
136
+
137
+ return {
138
+ entryPoint: {
139
+ version: entryPointVersion,
140
+ address: entryPointVersion === "v0.6" ? ENTRYPOINT_ADDRESS_V06 : ENTRYPOINT_ADDRESS_V07,
141
+ },
142
+ kernelVersion,
143
+ userId,
144
+ existingSignerConfig: this.getSigner(signers),
145
+ smartContractWalletAddress:
146
+ smartContractWalletAddress != null ? getAddress(smartContractWalletAddress) : undefined,
147
+ };
148
+ }
149
+
150
+ private getSigner(signers: any[]): SignerData | undefined {
151
+ if (signers.length === 0) {
152
+ return undefined;
153
+ }
154
+
155
+ if (signers.length > 1) {
156
+ throw new CrossmintServiceError("Invalid wallet signer configuration. Please contact support");
157
+ }
158
+
159
+ return signers[0].signerData;
160
+ }
161
+ }
162
+
163
+ class AccountFactory {
164
+ constructor(private readonly eoa: EOAAccountService, private readonly passkey: PasskeyAccountService) {}
165
+
166
+ public get(
167
+ params: WalletCreationParams,
168
+ existingSignerConfig?: SignerData
169
+ ): Promise<{
170
+ signerData: SignerData;
171
+ account: KernelSmartAccount<EntryPoint, HttpTransport>;
172
+ }> {
173
+ if (isPasskeyParams(params)) {
174
+ if (existingSignerConfig != null && existingSignerConfig?.type !== "passkeys") {
175
+ throw new AdminMismatchError(
176
+ `Cannot create wallet with passkey signer for user '${params.user.id}', they have an existing wallet with eoa signer '${existingSignerConfig.eoaAddress}.'`,
177
+ existingSignerConfig
178
+ );
179
+ }
180
+
181
+ return this.passkey.get(params, existingSignerConfig);
182
+ }
183
+
184
+ if (existingSignerConfig != null && existingSignerConfig?.type !== "eoa") {
185
+ throw new AdminMismatchError(
186
+ `Cannot create wallet with eoa signer for user '${params.user.id}', they already have a wallet with a passkey named '${existingSignerConfig.passkeyName}' as it's signer.`,
187
+ displayPasskey(existingSignerConfig)
188
+ );
189
+ }
190
+
191
+ return this.eoa.get(params as EOAWalletParams, existingSignerConfig);
192
+ }
193
+ }
@@ -0,0 +1,148 @@
1
+ import { PasskeyDisplay, SignerDisplay } from "@/types/API";
2
+
3
+ export const SmartWalletErrors = {
4
+ NOT_AUTHORIZED: "smart-wallet:not-authorized",
5
+ TRANSFER: "smart-wallet:transfer.error",
6
+ CROSSMINT_SERVICE: "smart-wallet:crossmint-service.error",
7
+ ERROR_JWT_EXPIRED: "smart-wallet:not-authorized.jwt-expired",
8
+ ERROR_JWT_INVALID: "smart-wallet:not-authorized.jwt-invalid",
9
+ ERROR_JWT_DECRYPTION: "smart-wallet:not-authorized.jwt-decryption",
10
+ ERROR_JWT_IDENTIFIER: "smart-wallet:not-authorized.jwt-identifier",
11
+ ERROR_USER_WALLET_ALREADY_CREATED: "smart-wallet:user-wallet-already-created.error",
12
+ ERROR_OUT_OF_CREDITS: "smart-wallet:out-of-credits.error",
13
+ ERROR_WALLET_CONFIG: "smart-wallet:wallet-config.error",
14
+ ERROR_ADMIN_MISMATCH: "smart-wallet:wallet-config.admin-mismatch",
15
+ ERROR_PASSKEY_MISMATCH: "smart-wallet:wallet-config.passkey-mismatch",
16
+ ERROR_ADMIN_SIGNER_ALREADY_USED: "smart-wallet:wallet-config.admin-signer-already-used",
17
+ UNCATEGORIZED: "smart-wallet:uncategorized", // catch-all error code
18
+ } as const;
19
+ export type SmartWalletErrorCode = (typeof SmartWalletErrors)[keyof typeof SmartWalletErrors];
20
+
21
+ export class SmartWalletSDKError extends Error {
22
+ public readonly code: SmartWalletErrorCode;
23
+ public readonly details?: string;
24
+
25
+ constructor(message: string, details?: string, code: SmartWalletErrorCode = SmartWalletErrors.UNCATEGORIZED) {
26
+ super(message);
27
+ this.details = details;
28
+ this.code = code;
29
+ }
30
+ }
31
+
32
+ export class TransferError extends SmartWalletSDKError {
33
+ constructor(message: string) {
34
+ super(message, undefined, SmartWalletErrors.TRANSFER);
35
+ }
36
+ }
37
+
38
+ export class CrossmintServiceError extends SmartWalletSDKError {
39
+ public status?: number;
40
+
41
+ constructor(message: string, status?: number) {
42
+ super(message, undefined, SmartWalletErrors.CROSSMINT_SERVICE);
43
+ this.status = status;
44
+ }
45
+ }
46
+
47
+ export class AdminMismatchError extends SmartWalletSDKError {
48
+ public readonly required: SignerDisplay;
49
+ public readonly used?: SignerDisplay;
50
+
51
+ constructor(message: string, required: SignerDisplay, used?: SignerDisplay) {
52
+ super(message, SmartWalletErrors.ERROR_ADMIN_MISMATCH);
53
+ this.required = required;
54
+ this.used = used;
55
+ }
56
+ }
57
+
58
+ export class PasskeyMismatchError extends SmartWalletSDKError {
59
+ public readonly required: PasskeyDisplay;
60
+ public readonly used?: PasskeyDisplay;
61
+
62
+ constructor(message: string, required: PasskeyDisplay, used?: PasskeyDisplay) {
63
+ super(message, SmartWalletErrors.ERROR_PASSKEY_MISMATCH);
64
+ this.required = required;
65
+ this.used = used;
66
+ }
67
+ }
68
+
69
+ export class NotAuthorizedError extends SmartWalletSDKError {
70
+ constructor(message: string) {
71
+ super(message, undefined, SmartWalletErrors.NOT_AUTHORIZED);
72
+ }
73
+ }
74
+
75
+ export class JWTExpiredError extends NotAuthorizedError {
76
+ public readonly code = SmartWalletErrors.ERROR_JWT_EXPIRED;
77
+
78
+ /**
79
+ * The expiry time of the JWT as an ISO 8601 timestamp.
80
+ */
81
+ public readonly expiredAt: string;
82
+
83
+ constructor(expiredAt: Date) {
84
+ super(`JWT provided expired at timestamp ${expiredAt}`);
85
+ this.expiredAt = expiredAt.toISOString();
86
+ }
87
+ }
88
+
89
+ export class JWTInvalidError extends NotAuthorizedError {
90
+ public readonly code = SmartWalletErrors.ERROR_JWT_INVALID;
91
+ constructor() {
92
+ super("Invalid JWT provided");
93
+ }
94
+ }
95
+
96
+ export class JWTDecryptionError extends NotAuthorizedError {
97
+ public readonly code = SmartWalletErrors.ERROR_JWT_DECRYPTION;
98
+ constructor() {
99
+ super("Error decrypting JWT");
100
+ }
101
+ }
102
+
103
+ export class JWTIdentifierError extends NotAuthorizedError {
104
+ public readonly code = SmartWalletErrors.ERROR_JWT_IDENTIFIER;
105
+ public readonly identifierKey: string;
106
+
107
+ constructor(identifierKey: string) {
108
+ super(`Missing required identifier '${identifierKey}' in the JWT`);
109
+ this.identifierKey = identifierKey;
110
+ }
111
+ }
112
+
113
+ export class UserWalletAlreadyCreatedError extends SmartWalletSDKError {
114
+ public readonly code = SmartWalletErrors.ERROR_USER_WALLET_ALREADY_CREATED;
115
+
116
+ constructor(userId: string) {
117
+ super(`The user with userId ${userId.toString()} already has a wallet created for this project`);
118
+ }
119
+ }
120
+
121
+ export class OutOfCreditsError extends SmartWalletSDKError {
122
+ constructor(message?: string) {
123
+ super(
124
+ "You've run out of Crossmint API credits. Visit https://docs.crossmint.com/docs/errors for more information",
125
+ undefined,
126
+ SmartWalletErrors.ERROR_OUT_OF_CREDITS
127
+ );
128
+ }
129
+ }
130
+
131
+ export class ConfigError extends SmartWalletSDKError {
132
+ constructor(message: string) {
133
+ super(message, undefined, SmartWalletErrors.ERROR_WALLET_CONFIG);
134
+ }
135
+ }
136
+
137
+ export class AdminAlreadyUsedError extends ConfigError {
138
+ public readonly code = SmartWalletErrors.ERROR_ADMIN_SIGNER_ALREADY_USED;
139
+ constructor() {
140
+ super("This signer was already used to create another wallet. Please use a different signer.");
141
+ }
142
+ }
143
+
144
+ export class NonCustodialWalletsNotEnabledError extends ConfigError {
145
+ constructor() {
146
+ super("Non-custodial wallets are not enabled for this project");
147
+ }
148
+ }
@@ -0,0 +1,36 @@
1
+ import { logError } from "@/services/logging";
2
+ import { DatadogProvider } from "@/services/logging/DatadogProvider";
3
+ import { SDK_VERSION } from "@/utils/constants";
4
+ import { BaseError, stringify } from "viem";
5
+
6
+ import { SmartWalletSDKError } from ".";
7
+
8
+ export class ErrorProcessor {
9
+ constructor(private readonly logger: DatadogProvider) {}
10
+
11
+ public map(error: unknown, fallback: SmartWalletSDKError): SmartWalletSDKError | BaseError {
12
+ this.record(error);
13
+
14
+ if (error instanceof SmartWalletSDKError) {
15
+ return error;
16
+ }
17
+
18
+ // Allow viem errors, which are generally pretty friendly.
19
+ if (error instanceof BaseError) {
20
+ return error;
21
+ }
22
+
23
+ return fallback;
24
+ }
25
+
26
+ private record(error: unknown) {
27
+ const message = error instanceof Error ? error.message : String(error);
28
+ this.logger.logError(`Smart Wallet SDK Error: ${message}`, {
29
+ stack: error instanceof Error ? error.stack : undefined,
30
+ name: error instanceof Error ? error.name : "UnknownError",
31
+ details: stringify(error),
32
+ domain: window.location.hostname,
33
+ sdk_version: SDK_VERSION,
34
+ });
35
+ }
36
+ }
package/src/index.ts ADDED
@@ -0,0 +1,34 @@
1
+ export { EVMBlockchainIncludingTestnet as Blockchain, blockchainToChainId } from "@crossmint/common-sdk-base";
2
+
3
+ export { EVMSmartWallet } from "./blockchain/wallets/EVMSmartWallet";
4
+
5
+ export type {
6
+ SmartWalletSDKInitParams,
7
+ UserParams,
8
+ ViemAccount,
9
+ PasskeySigner,
10
+ EOASigner,
11
+ WalletParams,
12
+ } from "./types/Config";
13
+
14
+ export type { TransferType, ERC20TransferType, NFTTransferType, SFTTransferType } from "./types/Tokens";
15
+
16
+ export {
17
+ TransferError,
18
+ CrossmintServiceError,
19
+ SmartWalletSDKError,
20
+ JWTDecryptionError,
21
+ JWTExpiredError,
22
+ JWTIdentifierError,
23
+ JWTInvalidError,
24
+ NotAuthorizedError,
25
+ UserWalletAlreadyCreatedError,
26
+ OutOfCreditsError,
27
+ AdminAlreadyUsedError,
28
+ AdminMismatchError,
29
+ PasskeyMismatchError,
30
+ ConfigError,
31
+ NonCustodialWalletsNotEnabledError,
32
+ } from "./error";
33
+
34
+ export { SmartWalletSDK } from "./SmartWalletSDK";
@@ -0,0 +1,5 @@
1
+ export interface BrowserLoggerInterface {
2
+ logInfo(message: string, context?: unknown): void;
3
+ logError(message: string, context?: unknown): void;
4
+ logWarn(message: string, context?: unknown): void;
5
+ }
@@ -0,0 +1,24 @@
1
+ import { BrowserLoggerInterface } from "./BrowserLoggerInterface";
2
+
3
+ // Set to true to enable logging on local development
4
+ const LOG_IN_LOCALHOST = false;
5
+
6
+ export class ConsoleProvider implements BrowserLoggerInterface {
7
+ logInfo(message: string, context?: object) {
8
+ if (LOG_IN_LOCALHOST) {
9
+ console.log(message, context);
10
+ }
11
+ }
12
+
13
+ logError(message: string, context?: object) {
14
+ if (LOG_IN_LOCALHOST) {
15
+ console.error(message, context);
16
+ }
17
+ }
18
+
19
+ logWarn(message: string, context?: object) {
20
+ if (LOG_IN_LOCALHOST) {
21
+ console.warn(message, context);
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,39 @@
1
+ import { DATADOG_CLIENT_TOKEN, SCW_SERVICE } from "@/utils/constants";
2
+ import { datadogLogs } from "@datadog/browser-logs";
3
+
4
+ import { BrowserLoggerInterface } from "./BrowserLoggerInterface";
5
+
6
+ export class DatadogProvider implements BrowserLoggerInterface {
7
+ logInfo(message: string, context?: object) {
8
+ log(message, "info", context);
9
+ }
10
+
11
+ logError(message: string, context?: object) {
12
+ log(message, "error", context);
13
+ }
14
+
15
+ logWarn(message: string, context?: object) {
16
+ log(message, "warn", context);
17
+ }
18
+ }
19
+
20
+ function log(message: string, loggerType: "info" | "error" | "warn", contextParam?: object) {
21
+ const _context = contextParam ? { ...contextParam, service: SCW_SERVICE } : { service: SCW_SERVICE };
22
+
23
+ init();
24
+ datadogLogs.logger[loggerType](message, _context);
25
+ }
26
+
27
+ function init() {
28
+ const isDatadogInitialized = datadogLogs.getInternalContext() != null;
29
+ if (isDatadogInitialized) {
30
+ return;
31
+ }
32
+
33
+ datadogLogs.init({
34
+ clientToken: DATADOG_CLIENT_TOKEN,
35
+ site: "datadoghq.com",
36
+ forwardErrorsToLogs: false,
37
+ sampleRate: 100,
38
+ });
39
+ }
@@ -0,0 +1,16 @@
1
+ import { isClient } from "../../utils/environment";
2
+ import { isLocalhost } from "../../utils/helpers";
3
+ import { ConsoleProvider } from "./ConsoleProvider";
4
+ import { DatadogProvider } from "./DatadogProvider";
5
+
6
+ function getBrowserLogger() {
7
+ if (isClient() && isLocalhost()) {
8
+ return new ConsoleProvider();
9
+ }
10
+
11
+ return new DatadogProvider();
12
+ }
13
+
14
+ const { logInfo, logWarn, logError } = getBrowserLogger();
15
+
16
+ export { logInfo, logWarn, logError };
@@ -0,0 +1,40 @@
1
+ import { PasskeyValidatorContractVersion } from "@zerodev/passkey-validator";
2
+
3
+ import { PasskeyValidatorSerializedData, SupportedEntryPointVersion, SupportedKernelVersion } from "./internal";
4
+
5
+ export type StoreSmartWalletParams = {
6
+ type: string;
7
+ smartContractWalletAddress: string;
8
+ signerData: SignerData;
9
+ sessionKeySignerAddress?: string;
10
+ version: number;
11
+ baseLayer: string;
12
+ chainId: number;
13
+ entryPointVersion: SupportedEntryPointVersion;
14
+ kernelVersion: SupportedKernelVersion;
15
+ };
16
+
17
+ export type SignerData = EOASignerData | PasskeySignerData;
18
+
19
+ export interface EOASignerData {
20
+ eoaAddress: string;
21
+ type: "eoa";
22
+ }
23
+
24
+ export type PasskeySignerData = PasskeyValidatorSerializedData & {
25
+ passkeyName: string;
26
+ validatorContractVersion: PasskeyValidatorContractVersion;
27
+ domain: string;
28
+ type: "passkeys";
29
+ };
30
+
31
+ export type PasskeyDisplay = Pick<PasskeySignerData, "type" | "passkeyName" | "pubKeyX" | "pubKeyY">;
32
+ export type SignerDisplay = EOASignerData | PasskeyDisplay;
33
+ export function displayPasskey(data: PasskeySignerData): PasskeyDisplay {
34
+ return {
35
+ pubKeyX: data.pubKeyX,
36
+ pubKeyY: data.pubKeyY,
37
+ passkeyName: data.passkeyName,
38
+ type: "passkeys",
39
+ };
40
+ }
@@ -0,0 +1,35 @@
1
+ import type { EntryPoint } from "permissionless/types/entrypoint";
2
+ import type { EIP1193Provider, LocalAccount } from "viem";
3
+
4
+ import type { SupportedEntryPointVersion } from "./internal";
5
+
6
+ export type SmartWalletSDKInitParams = {
7
+ clientApiKey: string;
8
+ };
9
+
10
+ export type UserParams = {
11
+ jwt: string;
12
+ };
13
+
14
+ export type ViemAccount = {
15
+ type: "VIEM_ACCOUNT";
16
+ account: LocalAccount & { source: "custom" };
17
+ };
18
+
19
+ export type PasskeySigner = {
20
+ type: "PASSKEY";
21
+
22
+ /**
23
+ * Displayed to the user during passkey registration or signing prompts.
24
+ * If not provided, a default name identifier within the JWT
25
+ * that is specified in the project settings (typically `sub`) will be used.
26
+ */
27
+ passkeyName?: string;
28
+ };
29
+
30
+ export type EOASigner = EIP1193Provider | ViemAccount;
31
+ export interface WalletParams {
32
+ signer: EOASigner | PasskeySigner;
33
+ }
34
+
35
+ export type EntryPointDetails = { version: SupportedEntryPointVersion; address: EntryPoint };
@@ -0,0 +1,27 @@
1
+ import { EVMBlockchainIncludingTestnet } from "@crossmint/common-sdk-base";
2
+
3
+ export interface EVMToken {
4
+ chain: EVMBlockchainIncludingTestnet;
5
+ contractAddress: string;
6
+ }
7
+
8
+ export interface NFTEVMToken extends EVMToken {
9
+ tokenId: string;
10
+ type: "nft";
11
+ }
12
+
13
+ export interface SFTEVMToken extends EVMToken {
14
+ tokenId: string;
15
+ type: "sft";
16
+ }
17
+
18
+ export interface ERC2OEVMToken extends EVMToken {
19
+ type: "ft";
20
+ }
21
+
22
+ export type TokenType = "nft" | "sft" | "ft";
23
+
24
+ export type ERC20TransferType = { token: ERC2OEVMToken; amount: bigint };
25
+ export type SFTTransferType = { token: SFTEVMToken; quantity: number };
26
+ export type NFTTransferType = { token: NFTEVMToken };
27
+ export type TransferType = ERC20TransferType | SFTTransferType | NFTTransferType;
@@ -0,0 +1,50 @@
1
+ import type { KernelSmartAccount } from "@zerodev/sdk";
2
+ import type { SmartAccountClient } from "permissionless";
3
+ import type { SmartAccount } from "permissionless/accounts";
4
+ import type { EntryPoint } from "permissionless/types/entrypoint";
5
+ import type { Chain, Hex, HttpTransport, PublicClient } from "viem";
6
+
7
+ import type { EVMBlockchainIncludingTestnet } from "@crossmint/common-sdk-base";
8
+
9
+ import type { SignerData } from "./API";
10
+ import type { EntryPointDetails, UserParams, WalletParams } from "./Config";
11
+
12
+ export const SUPPORTED_KERNEL_VERSIONS = ["0.3.1", "0.3.0", "0.2.4"] as const;
13
+ export type SupportedKernelVersion = (typeof SUPPORTED_KERNEL_VERSIONS)[number];
14
+
15
+ export function isSupportedKernelVersion(version: string): version is SupportedKernelVersion {
16
+ return SUPPORTED_KERNEL_VERSIONS.includes(version as any);
17
+ }
18
+
19
+ export const SUPPORTED_ENTRYPOINT_VERSIONS = ["v0.6", "v0.7"] as const;
20
+ export type SupportedEntryPointVersion = (typeof SUPPORTED_ENTRYPOINT_VERSIONS)[number];
21
+
22
+ export function isSupportedEntryPointVersion(version: string): version is SupportedEntryPointVersion {
23
+ return SUPPORTED_ENTRYPOINT_VERSIONS.includes(version as any);
24
+ }
25
+
26
+ export interface WalletCreationParams {
27
+ user: UserParams & { id: string };
28
+ chain: EVMBlockchainIncludingTestnet;
29
+ publicClient: PublicClient<HttpTransport>;
30
+ walletParams: WalletParams;
31
+ entryPoint: EntryPointDetails;
32
+ kernelVersion: SupportedKernelVersion;
33
+ }
34
+
35
+ export interface AccountAndSigner {
36
+ account: KernelSmartAccount<EntryPoint, HttpTransport>;
37
+ signerData: SignerData;
38
+ }
39
+
40
+ export type PasskeyValidatorSerializedData = {
41
+ passkeyServerUrl: string;
42
+ entryPoint: Hex;
43
+ validatorAddress: Hex;
44
+ pubKeyX: string;
45
+ pubKeyY: string;
46
+ authenticatorIdHash: Hex;
47
+ authenticatorId: string;
48
+ };
49
+
50
+ export type SmartWalletClient = SmartAccountClient<EntryPoint, HttpTransport, Chain, SmartAccount<EntryPoint>>;
@@ -0,0 +1,15 @@
1
+ import { EVMBlockchainIncludingTestnet } from "@crossmint/common-sdk-base";
2
+
3
+ function isPolygonCDK(chain: EVMBlockchainIncludingTestnet) {
4
+ const polygonCDKchains: EVMBlockchainIncludingTestnet[] = [
5
+ EVMBlockchainIncludingTestnet.ZKYOTO,
6
+ EVMBlockchainIncludingTestnet.ZKATANA,
7
+ EVMBlockchainIncludingTestnet.ASTAR_ZKEVM,
8
+ EVMBlockchainIncludingTestnet.HYPERSONIC_TESTNET,
9
+ ];
10
+ return polygonCDKchains.includes(chain);
11
+ }
12
+
13
+ export function usesGelatoBundler(chain: EVMBlockchainIncludingTestnet) {
14
+ return isPolygonCDK(chain);
15
+ }