@crossmint/client-sdk-smart-wallet 0.1.2 → 0.1.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 (42) hide show
  1. package/dist/index.cjs +4 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +254 -119
  4. package/dist/index.d.ts +254 -119
  5. package/dist/index.js +4 -1
  6. package/dist/index.js.map +1 -1
  7. package/package.json +5 -13
  8. package/src/SmartWalletSDK.test.ts +12 -13
  9. package/src/SmartWalletSDK.ts +33 -26
  10. package/src/api/APIErrorService.ts +10 -7
  11. package/src/api/BaseCrossmintService.ts +3 -4
  12. package/src/api/CrossmintWalletService.test.ts +9 -9
  13. package/src/api/CrossmintWalletService.ts +39 -16
  14. package/src/blockchain/chains.ts +25 -2
  15. package/src/blockchain/transfer.ts +1 -1
  16. package/src/blockchain/wallets/EVMSmartWallet.ts +49 -42
  17. package/src/blockchain/wallets/account/config.ts +60 -0
  18. package/src/blockchain/wallets/account/creator.ts +36 -0
  19. package/src/blockchain/wallets/account/eoa.ts +50 -0
  20. package/src/blockchain/wallets/{passkey.ts → account/passkey.ts} +32 -32
  21. package/src/blockchain/wallets/account/signer.ts +44 -0
  22. package/src/blockchain/wallets/account/strategy.ts +5 -0
  23. package/src/blockchain/wallets/clientDecorator.ts +6 -6
  24. package/src/blockchain/wallets/paymaster.ts +12 -15
  25. package/src/blockchain/wallets/service.ts +38 -143
  26. package/src/error/index.ts +25 -117
  27. package/src/error/processor.ts +5 -6
  28. package/src/index.ts +16 -12
  29. package/src/services/logging/ConsoleProvider.ts +3 -12
  30. package/src/services/logging/DatadogProvider.ts +1 -1
  31. package/src/types/internal.ts +41 -20
  32. package/src/types/{Config.ts → params.ts} +0 -5
  33. package/src/types/schema.ts +63 -0
  34. package/src/types/service.ts +31 -0
  35. package/src/utils/api.ts +39 -0
  36. package/src/utils/constants.ts +2 -0
  37. package/src/utils/log.ts +1 -109
  38. package/src/utils/signer.ts +14 -16
  39. package/src/blockchain/wallets/eoa.ts +0 -49
  40. package/src/types/API.ts +0 -40
  41. package/src/utils/log.test.ts +0 -76
  42. /package/src/types/{Tokens.ts → token.ts} +0 -0
package/src/utils/log.ts CHANGED
@@ -1,115 +1,15 @@
1
- import { v4 as uuidv4 } from "uuid";
2
-
3
1
  import { logError, logInfo } from "../services/logging";
4
2
  import { SCW_SERVICE } from "./constants";
5
- import { isLocalhost } from "./helpers";
6
-
7
- export class LoggerWrapper {
8
- constructor(className: string, private extraInfo = {}, private logIdempotencyKey = uuidv4()) {
9
- return new Proxy(this, {
10
- get: (target: any, propKey: PropertyKey, receiver: any) => {
11
- const origMethod = target[propKey];
12
- const identifierTag = `[${SCW_SERVICE} - ${className} - ${String(propKey)}]`;
13
-
14
- if (typeof origMethod === "function") {
15
- return (...args: any[]) => {
16
- this.logInput(args, identifierTag);
17
-
18
- const result = origMethod.apply(target, args);
19
- if (result instanceof Promise) {
20
- return result
21
- .then((res: any) => {
22
- this.logOutput(res, identifierTag);
23
- return res;
24
- })
25
- .catch((err: any) => {
26
- this.logError(err, identifierTag);
27
- throw err;
28
- });
29
- } else {
30
- this.logOutput(result, identifierTag);
31
- return result;
32
- }
33
- };
34
- }
35
- return Reflect.get(target, propKey, receiver);
36
- },
37
- });
38
- }
39
-
40
- private logInput(args: object, identifierTag: string) {
41
- logInfoIfNotInLocalhost(
42
- `${identifierTag} input - ${beautify(args)} - extra_info - ${beautify(
43
- this.extraInfo
44
- )} - log_idempotency_key - ${this.logIdempotencyKey}`,
45
- { args, ...this.extraInfo, logIdempotencyKey: this.logIdempotencyKey }
46
- );
47
- }
48
-
49
- private logOutput(res: object, identifierTag: string) {
50
- logInfoIfNotInLocalhost(
51
- `${identifierTag} output - ${beautify(res)} - extra_info - ${beautify(
52
- this.extraInfo
53
- )} - log_idempotency_key - ${this.logIdempotencyKey}`,
54
- {
55
- res,
56
- ...this.extraInfo,
57
- logIdempotencyKey: this.logIdempotencyKey,
58
- }
59
- );
60
- }
61
-
62
- private logError(err: object, identifierTag: string) {
63
- logError(
64
- `${identifierTag} threw_error - ${err} - extra_info - ${beautify(this.extraInfo)} - log_idempotency_key - ${
65
- this.logIdempotencyKey
66
- }`,
67
- { err, ...this.extraInfo }
68
- );
69
- }
70
-
71
- protected logPerformance<T>(name: string, cb: () => Promise<T>) {
72
- return logPerformance(name, cb, this.extraInfo);
73
- }
74
- }
75
3
 
76
4
  export async function logPerformance<T>(name: string, cb: () => Promise<T>, extraInfo?: object) {
77
5
  const start = new Date().getTime();
78
6
  const result = await cb();
79
7
  const durationInMs = new Date().getTime() - start;
80
8
  const args = { durationInMs, ...extraInfo };
81
- logInfoIfNotInLocalhost(`[${SCW_SERVICE} - ${name} - TIME] - ${beautify(args)}`, { args });
9
+ logInfo(`[${SCW_SERVICE} - ${name} - TIME] - ${beautify(args)}`, { args });
82
10
  return result;
83
11
  }
84
12
 
85
- export function logInputOutput<T, A extends any[]>(fn: (...args: A) => T, functionName: string): (...args: A) => T {
86
- return function (this: any, ...args: A): T {
87
- const identifierTag = `[${SCW_SERVICE} - function: ${functionName}]`;
88
- logInfoIfNotInLocalhost(`${identifierTag} input: ${beautify(args)}`, { args });
89
-
90
- try {
91
- const result = fn.apply(this, args);
92
- if (result instanceof Promise) {
93
- return result
94
- .then((res) => {
95
- logInfoIfNotInLocalhost(`${identifierTag} output: ${beautify(res)}`, { res });
96
- return res;
97
- })
98
- .catch((err) => {
99
- logError(`${identifierTag} threw_error: ${beautify(err)}`, { err });
100
- throw err;
101
- }) as T;
102
- } else {
103
- logInfoIfNotInLocalhost(`${identifierTag} output: ${beautify(result)}`, { res: result });
104
- return result;
105
- }
106
- } catch (err) {
107
- logError(`${identifierTag} threw_error: ${beautify(err)}`, { err });
108
- throw err;
109
- }
110
- };
111
- }
112
-
113
13
  function beautify(json: any) {
114
14
  try {
115
15
  return json != null ? JSON.stringify(json, null, 2) : json;
@@ -137,14 +37,6 @@ function stringifyAvoidingCircular(json: any) {
137
37
  return JSON.stringify(simpleObject, null, 2); // returns cleaned up JSON
138
38
  }
139
39
 
140
- function logInfoIfNotInLocalhost(message: string, context?: object) {
141
- if (isLocalhost()) {
142
- console.log(message);
143
- return;
144
- }
145
- logInfo(message, context);
146
- }
147
-
148
40
  export function errorToJSON(error: Error | unknown) {
149
41
  const errorToLog = error instanceof Error ? error : { message: "Unknown error", name: "Unknown error" };
150
42
 
@@ -3,28 +3,26 @@ import type { SmartAccountSigner } from "permissionless/accounts";
3
3
  import { Address, EIP1193Provider } from "viem";
4
4
 
5
5
  import { SmartWalletChain } from "../blockchain/chains";
6
- import { SmartWalletSDKError } from "../error";
7
- import { ViemAccount, WalletParams } from "../types/Config";
8
- import { logInputOutput } from "./log";
6
+ import { SmartWalletError } from "../error";
7
+ import { ViemAccount, WalletParams } from "../types/params";
9
8
 
10
9
  type CreateOwnerSignerInput = {
11
10
  chain: SmartWalletChain;
12
11
  walletParams: WalletParams;
13
12
  };
14
13
 
15
- export const createOwnerSigner = logInputOutput(
16
- async ({ walletParams }: CreateOwnerSignerInput): Promise<SmartAccountSigner<"custom", Address>> => {
17
- if (isEIP1193Provider(walletParams.signer)) {
18
- return await providerToSmartAccountSigner(walletParams.signer);
19
- } else if (isAccount(walletParams.signer)) {
20
- return walletParams.signer.account;
21
- } else {
22
- const signer = walletParams.signer as any;
23
- throw new SmartWalletSDKError(`The signer type ${signer.type} is not supported`);
24
- }
25
- },
26
- "createOwnerSigner"
27
- );
14
+ export async function createOwnerSigner({
15
+ walletParams,
16
+ }: CreateOwnerSignerInput): Promise<SmartAccountSigner<"custom", Address>> {
17
+ if (isEIP1193Provider(walletParams.signer)) {
18
+ return await providerToSmartAccountSigner(walletParams.signer);
19
+ } else if (isAccount(walletParams.signer)) {
20
+ return walletParams.signer.account;
21
+ } else {
22
+ const signer = walletParams.signer as any;
23
+ throw new SmartWalletError(`The signer type ${signer.type} is not supported`);
24
+ }
25
+ }
28
26
 
29
27
  function isEIP1193Provider(signer: any): signer is EIP1193Provider {
30
28
  return signer && typeof signer.request === "function";
@@ -1,49 +0,0 @@
1
- import { EOASignerData } from "@/types/API";
2
- import type { EOASigner, WalletParams } from "@/types/Config";
3
- import { AccountAndSigner, WalletCreationParams } from "@/types/internal";
4
- import { equalsIgnoreCase } from "@/utils/helpers";
5
- import { createOwnerSigner } from "@/utils/signer";
6
- import { signerToEcdsaValidator } from "@zerodev/ecdsa-validator";
7
- import { createKernelAccount } from "@zerodev/sdk";
8
-
9
- import { AdminMismatchError } from "../../error";
10
-
11
- export interface EOAWalletParams extends WalletCreationParams {
12
- walletParams: WalletParams & { signer: EOASigner };
13
- }
14
-
15
- export class EOAAccountService {
16
- public async get(
17
- { chain, publicClient, entryPoint, walletParams, kernelVersion, user }: EOAWalletParams,
18
- existingSignerConfig?: EOASignerData
19
- ): Promise<AccountAndSigner> {
20
- const eoa = await createOwnerSigner({
21
- chain,
22
- walletParams,
23
- });
24
-
25
- if (existingSignerConfig != null && !equalsIgnoreCase(eoa.address, existingSignerConfig.eoaAddress)) {
26
- throw new AdminMismatchError(
27
- `User '${user.id}' has an existing wallet with an eoa signer '${existingSignerConfig.eoaAddress}', this does not match input eoa signer '${eoa.address}'.`,
28
- existingSignerConfig,
29
- { type: "eoa", eoaAddress: existingSignerConfig.eoaAddress }
30
- );
31
- }
32
-
33
- const ecdsaValidator = await signerToEcdsaValidator(publicClient, {
34
- signer: eoa,
35
- entryPoint: entryPoint.address,
36
- kernelVersion,
37
- });
38
- const account = await createKernelAccount(publicClient, {
39
- plugins: {
40
- sudo: ecdsaValidator,
41
- },
42
- index: BigInt(0),
43
- entryPoint: entryPoint.address,
44
- kernelVersion,
45
- });
46
-
47
- return { account, signerData: { eoaAddress: eoa.address, type: "eoa" } };
48
- }
49
- }
package/src/types/API.ts DELETED
@@ -1,40 +0,0 @@
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
- }
@@ -1,76 +0,0 @@
1
- import { logInfo } from "../services/logging";
2
- import { LoggerWrapper } from "./log";
3
- import * as logModule from "./log";
4
-
5
- jest.mock("../services/logging");
6
-
7
- describe("Log test", () => {
8
- beforeEach(() => {
9
- jest.clearAllMocks();
10
- });
11
-
12
- describe("LoggerWrapper", () => {
13
- const addOne = (input: number): number => input + 1;
14
-
15
- class BaseClass extends LoggerWrapper {
16
- constructor() {
17
- super("BaseClass");
18
- }
19
-
20
- someMethod(input: number): any {
21
- return addOne(input);
22
- }
23
- }
24
-
25
- it("should return the same value and log the input and output of myMethod", () => {
26
- const base = new BaseClass();
27
- const input = 2;
28
- const result = base.someMethod(input);
29
-
30
- expect(result).toEqual(addOne(input));
31
- expect(logInfo).toHaveBeenCalledTimes(2);
32
-
33
- const logInfoCalls = (logInfo as jest.MockedFunction<typeof logInfo>).mock.calls;
34
- expect(logInfoCalls[0][0].includes("input")).toBeTruthy();
35
- expect(logInfoCalls[0][0].includes(String(input))).toBeTruthy();
36
- expect(logInfoCalls[1][0].includes("output")).toBeTruthy();
37
- expect(logInfoCalls[1][0].includes(String(result))).toBeTruthy();
38
- });
39
- });
40
-
41
- describe("logInputOutput", () => {
42
- const addTwo = (input: number): number => input + 2;
43
-
44
- it("should log the input and output of the function", () => {
45
- const addTwoWithLogging = logModule.logInputOutput((arg: number) => addTwo(arg), "addTwo");
46
-
47
- const input = 2;
48
- const result = addTwoWithLogging(input);
49
-
50
- expect(result).toEqual(addTwo(input));
51
- expect(logInfo).toHaveBeenCalledTimes(2);
52
-
53
- const logInfoCalls = (logInfo as jest.MockedFunction<typeof logInfo>).mock.calls;
54
- expect(logInfoCalls[0][0].includes("input")).toBeTruthy();
55
- expect(logInfoCalls[0][0].includes(String(input))).toBeTruthy();
56
- expect(logInfoCalls[1][0].includes("output")).toBeTruthy();
57
- expect(logInfoCalls[1][0].includes(String(result))).toBeTruthy();
58
- });
59
- });
60
-
61
- describe("logPerformance", () => {
62
- const addThree = async (input: number): Promise<number> => input + 3;
63
-
64
- it("should log the time", async () => {
65
- const input = 3;
66
-
67
- const result = await logModule.logPerformance("addThreeString", () => addThree(input));
68
-
69
- expect(result).toEqual(await addThree(input));
70
- expect(logInfo).toHaveBeenCalledTimes(1);
71
-
72
- const logInfoCalls = (logInfo as jest.MockedFunction<typeof logInfo>).mock.calls;
73
- expect(logInfoCalls[0][0].includes("TIME")).toBeTruthy();
74
- });
75
- });
76
- });
File without changes