@crossmint/client-sdk-smart-wallet 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -2
- package/dist/index.d.ts +17 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/blockchain/wallets/passkey.ts +80 -25
- package/src/error/index.ts +42 -0
- package/src/index.ts +4 -2
- package/src/types/Tokens.ts +1 -1
- package/src/types/internal.ts +1 -1
- package/src/utils/blockchain.ts +1 -1
- package/src/utils/signer.ts +1 -1
- package/src/blockchain/token/index.ts +0 -1
|
@@ -3,11 +3,17 @@ import { type PasskeySignerData, displayPasskey } from "@/types/API";
|
|
|
3
3
|
import type { PasskeySigner, UserParams, WalletParams } from "@/types/Config";
|
|
4
4
|
import type { AccountAndSigner, PasskeyValidatorSerializedData, WalletCreationParams } from "@/types/internal";
|
|
5
5
|
import { PasskeyValidatorContractVersion, WebAuthnMode, toPasskeyValidator } from "@zerodev/passkey-validator";
|
|
6
|
-
import { type KernelValidator, createKernelAccount } from "@zerodev/sdk";
|
|
7
|
-
import { WebAuthnKey, toWebAuthnKey } from "@zerodev/webauthn-key";
|
|
6
|
+
import { type KernelSmartAccount, type KernelValidator, createKernelAccount } from "@zerodev/sdk";
|
|
7
|
+
import { type WebAuthnKey, toWebAuthnKey } from "@zerodev/webauthn-key";
|
|
8
|
+
import type { SmartAccount } from "permissionless/accounts";
|
|
8
9
|
import type { EntryPoint } from "permissionless/types/entrypoint";
|
|
9
10
|
|
|
10
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
PasskeyIncompatibleAuthenticatorError,
|
|
13
|
+
PasskeyMismatchError,
|
|
14
|
+
PasskeyPromptError,
|
|
15
|
+
PasskeyRegistrationError,
|
|
16
|
+
} from "../../error";
|
|
11
17
|
|
|
12
18
|
export interface PasskeyWalletParams extends WalletCreationParams {
|
|
13
19
|
walletParams: WalletParams & { signer: PasskeySigner };
|
|
@@ -20,7 +26,6 @@ export function isPasskeyParams(params: WalletCreationParams): params is Passkey
|
|
|
20
26
|
type PasskeyValidator = KernelValidator<EntryPoint, "WebAuthnValidator"> & {
|
|
21
27
|
getSerializedData: () => string;
|
|
22
28
|
};
|
|
23
|
-
|
|
24
29
|
export class PasskeyAccountService {
|
|
25
30
|
constructor(private readonly crossmintService: CrossmintWalletService) {}
|
|
26
31
|
|
|
@@ -36,28 +41,32 @@ export class PasskeyAccountService {
|
|
|
36
41
|
);
|
|
37
42
|
}
|
|
38
43
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
try {
|
|
45
|
+
const passkey = await this.getPasskey(user, inputPasskeyName, existingSignerConfig);
|
|
46
|
+
|
|
47
|
+
const latestValidatorVersion = PasskeyValidatorContractVersion.V0_0_2;
|
|
48
|
+
const validatorContractVersion =
|
|
49
|
+
existingSignerConfig == null ? latestValidatorVersion : existingSignerConfig.validatorContractVersion;
|
|
50
|
+
const validator = await toPasskeyValidator(publicClient, {
|
|
51
|
+
webAuthnKey: passkey,
|
|
52
|
+
entryPoint: entryPoint.address,
|
|
53
|
+
validatorContractVersion,
|
|
54
|
+
kernelVersion,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const kernelAccount = await createKernelAccount(publicClient, {
|
|
58
|
+
plugins: { sudo: validator },
|
|
59
|
+
entryPoint: entryPoint.address,
|
|
60
|
+
kernelVersion,
|
|
61
|
+
});
|
|
50
62
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
signerData: this.getSignerData(validator, validatorContractVersion, inputPasskeyName),
|
|
59
|
-
account: kernelAccount,
|
|
60
|
-
};
|
|
63
|
+
return {
|
|
64
|
+
signerData: this.getSignerData(validator, validatorContractVersion, inputPasskeyName),
|
|
65
|
+
account: this.decorate(kernelAccount, inputPasskeyName),
|
|
66
|
+
};
|
|
67
|
+
} catch (error) {
|
|
68
|
+
throw this.mapError(error, inputPasskeyName);
|
|
69
|
+
}
|
|
61
70
|
}
|
|
62
71
|
|
|
63
72
|
private async getPasskey(
|
|
@@ -102,6 +111,52 @@ export class PasskeyAccountService {
|
|
|
102
111
|
Authorization: `Bearer ${user.jwt}`,
|
|
103
112
|
};
|
|
104
113
|
}
|
|
114
|
+
|
|
115
|
+
private mapError(error: any, passkeyName: string) {
|
|
116
|
+
if (error.code === 0 && error.name === "DataError") {
|
|
117
|
+
return new PasskeyIncompatibleAuthenticatorError(passkeyName);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (error.message === "Registration not verified") {
|
|
121
|
+
return new PasskeyRegistrationError(passkeyName);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (error.code === "ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY" && error.name === "NotAllowedError") {
|
|
125
|
+
return new PasskeyPromptError(passkeyName);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return error;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private decorate<Account extends KernelSmartAccount<EntryPoint>>(account: Account, passkeyName: string): Account {
|
|
132
|
+
return new Proxy(account, {
|
|
133
|
+
get: (target, prop, receiver) => {
|
|
134
|
+
const original = Reflect.get(target, prop, receiver);
|
|
135
|
+
if (typeof original !== "function" || typeof prop !== "string" || !isAccountSigningMethod(prop)) {
|
|
136
|
+
return original;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return async (...args: any[]) => {
|
|
140
|
+
try {
|
|
141
|
+
return await original.call(target, ...args);
|
|
142
|
+
} catch (error) {
|
|
143
|
+
throw this.mapError(error, passkeyName);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const accountSigningMethods = [
|
|
152
|
+
"signMessage",
|
|
153
|
+
"signTypedData",
|
|
154
|
+
"signUserOperation",
|
|
155
|
+
"signTransaction",
|
|
156
|
+
] as const satisfies readonly (keyof SmartAccount<EntryPoint>)[];
|
|
157
|
+
|
|
158
|
+
function isAccountSigningMethod(method: string): method is (typeof accountSigningMethods)[number] {
|
|
159
|
+
return accountSigningMethods.includes(method as any);
|
|
105
160
|
}
|
|
106
161
|
|
|
107
162
|
const deserializePasskeyValidatorData = (params: string) => {
|
package/src/error/index.ts
CHANGED
|
@@ -13,6 +13,9 @@ export const SmartWalletErrors = {
|
|
|
13
13
|
ERROR_WALLET_CONFIG: "smart-wallet:wallet-config.error",
|
|
14
14
|
ERROR_ADMIN_MISMATCH: "smart-wallet:wallet-config.admin-mismatch",
|
|
15
15
|
ERROR_PASSKEY_MISMATCH: "smart-wallet:wallet-config.passkey-mismatch",
|
|
16
|
+
ERROR_PASSKEY_PROMPT: "smart-wallet:passkey.prompt",
|
|
17
|
+
ERROR_PASSKEY_INCOMPATIBLE_AUTHENTICATOR: "smart-wallet.passkey.incompatible-authenticator",
|
|
18
|
+
ERROR_PASSKEY_REGISTRATION: "smart-wallet:passkey.registration",
|
|
16
19
|
ERROR_ADMIN_SIGNER_ALREADY_USED: "smart-wallet:wallet-config.admin-signer-already-used",
|
|
17
20
|
ERROR_PROJECT_NONCUSTODIAL_WALLETS_NOT_ENABLED: "smart-wallet:wallet-config.non-custodial-wallets-not-enabled",
|
|
18
21
|
UNCATEGORIZED: "smart-wallet:uncategorized", // catch-all error code
|
|
@@ -119,6 +122,45 @@ export class UserWalletAlreadyCreatedError extends SmartWalletSDKError {
|
|
|
119
122
|
}
|
|
120
123
|
}
|
|
121
124
|
|
|
125
|
+
export class PasskeyPromptError extends SmartWalletSDKError {
|
|
126
|
+
public passkeyName: string;
|
|
127
|
+
|
|
128
|
+
constructor(passkeyName: string) {
|
|
129
|
+
super(
|
|
130
|
+
`Prompt was either cancelled or timed out for passkey ${passkeyName}`,
|
|
131
|
+
undefined,
|
|
132
|
+
SmartWalletErrors.ERROR_PASSKEY_PROMPT
|
|
133
|
+
);
|
|
134
|
+
this.passkeyName = passkeyName;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export class PasskeyRegistrationError extends SmartWalletSDKError {
|
|
139
|
+
public passkeyName: string;
|
|
140
|
+
|
|
141
|
+
constructor(passkeyName: string) {
|
|
142
|
+
super(
|
|
143
|
+
`Registration for passkey ${passkeyName} failed, either the registration took too long, or passkey signature vaildation failed.`,
|
|
144
|
+
undefined,
|
|
145
|
+
SmartWalletErrors.ERROR_PASSKEY_REGISTRATION
|
|
146
|
+
);
|
|
147
|
+
this.passkeyName = passkeyName;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export class PasskeyIncompatibleAuthenticatorError extends SmartWalletSDKError {
|
|
152
|
+
public passkeyName: string;
|
|
153
|
+
|
|
154
|
+
constructor(passkeyName: string) {
|
|
155
|
+
super(
|
|
156
|
+
`User selected authenticator for passkey ${passkeyName} is not compatible with Crossmint's Smart Wallets.`,
|
|
157
|
+
undefined,
|
|
158
|
+
SmartWalletErrors.ERROR_PASSKEY_INCOMPATIBLE_AUTHENTICATOR
|
|
159
|
+
);
|
|
160
|
+
this.passkeyName = passkeyName;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
122
164
|
export class OutOfCreditsError extends SmartWalletSDKError {
|
|
123
165
|
constructor(message?: string) {
|
|
124
166
|
super(
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { blockchainToChainId } from "@crossmint/common-sdk-base";
|
|
1
|
+
export { blockchainToChainId, EVMBlockchainIncludingTestnet as Chain } from "@crossmint/common-sdk-base";
|
|
2
2
|
|
|
3
3
|
export { EVMSmartWallet } from "./blockchain/wallets/EVMSmartWallet";
|
|
4
4
|
|
|
@@ -12,7 +12,6 @@ export type {
|
|
|
12
12
|
} from "./types/Config";
|
|
13
13
|
|
|
14
14
|
export type { TransferType, ERC20TransferType, NFTTransferType, SFTTransferType } from "./types/Tokens";
|
|
15
|
-
export { SmartWalletChain } from "./blockchain/chains";
|
|
16
15
|
|
|
17
16
|
export {
|
|
18
17
|
TransferError,
|
|
@@ -28,6 +27,9 @@ export {
|
|
|
28
27
|
AdminAlreadyUsedError,
|
|
29
28
|
AdminMismatchError,
|
|
30
29
|
PasskeyMismatchError,
|
|
30
|
+
PasskeyPromptError,
|
|
31
|
+
PasskeyRegistrationError,
|
|
32
|
+
PasskeyIncompatibleAuthenticatorError,
|
|
31
33
|
ConfigError,
|
|
32
34
|
NonCustodialWalletsNotEnabledError,
|
|
33
35
|
} from "./error";
|
package/src/types/Tokens.ts
CHANGED
package/src/types/internal.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { SmartAccount } from "permissionless/accounts";
|
|
|
4
4
|
import type { EntryPoint } from "permissionless/types/entrypoint";
|
|
5
5
|
import type { Chain, Hex, HttpTransport, PublicClient } from "viem";
|
|
6
6
|
|
|
7
|
-
import { SmartWalletChain } from "
|
|
7
|
+
import type { SmartWalletChain } from "../blockchain/chains";
|
|
8
8
|
import type { SignerData } from "./API";
|
|
9
9
|
import type { EntryPointDetails, UserParams, WalletParams } from "./Config";
|
|
10
10
|
|
package/src/utils/blockchain.ts
CHANGED
package/src/utils/signer.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { providerToSmartAccountSigner } from "permissionless";
|
|
|
2
2
|
import type { SmartAccountSigner } from "permissionless/accounts";
|
|
3
3
|
import { Address, EIP1193Provider } from "viem";
|
|
4
4
|
|
|
5
|
-
import { SmartWalletChain } from "
|
|
5
|
+
import { SmartWalletChain } from "../blockchain/chains";
|
|
6
6
|
import { SmartWalletSDKError } from "../error";
|
|
7
7
|
import { ViemAccount, WalletParams } from "../types/Config";
|
|
8
8
|
import { logInputOutput } from "./log";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./Tokens";
|