@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.
- package/dist/index.cjs +4 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +254 -119
- package/dist/index.d.ts +254 -119
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -13
- package/src/SmartWalletSDK.test.ts +12 -13
- package/src/SmartWalletSDK.ts +33 -26
- package/src/api/APIErrorService.ts +10 -7
- package/src/api/BaseCrossmintService.ts +3 -4
- package/src/api/CrossmintWalletService.test.ts +9 -9
- package/src/api/CrossmintWalletService.ts +39 -16
- package/src/blockchain/chains.ts +25 -2
- package/src/blockchain/transfer.ts +1 -1
- package/src/blockchain/wallets/EVMSmartWallet.ts +49 -42
- package/src/blockchain/wallets/account/config.ts +60 -0
- package/src/blockchain/wallets/account/creator.ts +36 -0
- package/src/blockchain/wallets/account/eoa.ts +50 -0
- package/src/blockchain/wallets/{passkey.ts → account/passkey.ts} +32 -32
- package/src/blockchain/wallets/account/signer.ts +44 -0
- package/src/blockchain/wallets/account/strategy.ts +5 -0
- package/src/blockchain/wallets/clientDecorator.ts +6 -6
- package/src/blockchain/wallets/paymaster.ts +12 -15
- package/src/blockchain/wallets/service.ts +38 -143
- package/src/error/index.ts +25 -117
- package/src/error/processor.ts +5 -6
- package/src/index.ts +16 -12
- package/src/services/logging/ConsoleProvider.ts +3 -12
- package/src/services/logging/DatadogProvider.ts +1 -1
- package/src/types/internal.ts +41 -20
- package/src/types/{Config.ts → params.ts} +0 -5
- package/src/types/schema.ts +63 -0
- package/src/types/service.ts +31 -0
- package/src/utils/api.ts +39 -0
- package/src/utils/constants.ts +2 -0
- package/src/utils/log.ts +1 -109
- package/src/utils/signer.ts +14 -16
- package/src/blockchain/wallets/eoa.ts +0 -49
- package/src/types/API.ts +0 -40
- package/src/utils/log.test.ts +0 -76
- /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
|
-
|
|
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
|
|
package/src/utils/signer.ts
CHANGED
|
@@ -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 {
|
|
7
|
-
import { ViemAccount, WalletParams } from "../types/
|
|
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
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
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
|
-
}
|
package/src/utils/log.test.ts
DELETED
|
@@ -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
|