@privacy-paymasters/sdk 0.0.1

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.
@@ -0,0 +1,6 @@
1
+ export { UserOperationBuilder } from "./src/builder.js";
2
+ export { BundlerClient } from "./src/bundlerClient.js";
3
+ export { PrivacyProtocolBuilder } from "./src/privacyProtocolBuilder.js";
4
+ export { TornadoBuilder, tornadoAbi } from "./src/tornadoBuilder.js";
5
+ export type { EIP1193Provider, GasConfig } from "./src/types.js";
6
+ export type { UserOperationGasPrice, GasPrice } from "./src/bundlerClient.js";
package/dist/index.js ADDED
@@ -0,0 +1,274 @@
1
+ // src/builder.ts
2
+ import { createPublicClient, custom } from "viem";
3
+ var entryPointAbi = [
4
+ {
5
+ type: "function",
6
+ name: "getNonce",
7
+ inputs: [
8
+ { name: "sender", type: "address" },
9
+ { name: "key", type: "uint192" }
10
+ ],
11
+ outputs: [{ name: "nonce", type: "uint256" }],
12
+ stateMutability: "view"
13
+ }
14
+ ];
15
+
16
+ class UserOperationBuilder {
17
+ sender;
18
+ calldata = "0x";
19
+ authorization;
20
+ paymaster;
21
+ paymasterData;
22
+ signature = "0x";
23
+ nonceKey = 0n;
24
+ gas = { type: "auto" };
25
+ factory;
26
+ factoryData;
27
+ constructor(sender) {
28
+ this.sender = sender;
29
+ }
30
+ withCalldata(calldata) {
31
+ this.calldata = calldata;
32
+ return this;
33
+ }
34
+ withPaymaster(paymaster) {
35
+ this.paymaster = paymaster;
36
+ return this;
37
+ }
38
+ withPaymasterData(data) {
39
+ this.paymasterData = data;
40
+ return this;
41
+ }
42
+ withSignature(signature) {
43
+ this.signature = signature;
44
+ return this;
45
+ }
46
+ withNonceKey(key) {
47
+ this.nonceKey = key;
48
+ return this;
49
+ }
50
+ withGas(gas) {
51
+ this.gas = gas;
52
+ return this;
53
+ }
54
+ withFactory(factory, factoryData) {
55
+ this.factory = factory;
56
+ this.factoryData = factoryData;
57
+ return this;
58
+ }
59
+ withAuthorization(auth) {
60
+ this.authorization = auth;
61
+ return this;
62
+ }
63
+ async build(provider, bundlerClient) {
64
+ const rpcClient = createPublicClient({ transport: custom(provider) });
65
+ const nonce = await rpcClient.readContract({
66
+ address: bundlerClient.entryPoint,
67
+ abi: entryPointAbi,
68
+ functionName: "getNonce",
69
+ args: [this.sender, this.nonceKey]
70
+ });
71
+ const skeleton = {
72
+ authorization: this.authorization,
73
+ sender: this.sender,
74
+ nonce,
75
+ factory: this.factory,
76
+ factoryData: this.factoryData,
77
+ callData: this.calldata,
78
+ callGasLimit: 0n,
79
+ verificationGasLimit: 0n,
80
+ preVerificationGas: 0n,
81
+ maxFeePerGas: 0n,
82
+ maxPriorityFeePerGas: 0n,
83
+ paymaster: this.paymaster,
84
+ paymasterVerificationGasLimit: 0n,
85
+ paymasterPostOpGasLimit: 0n,
86
+ paymasterData: this.paymasterData,
87
+ signature: this.signature
88
+ };
89
+ if (this.gas.type === "auto") {
90
+ const [est, gasPrice] = await Promise.all([
91
+ bundlerClient.estimateUserOperationGas(skeleton),
92
+ bundlerClient.getUserOperationGasPrice()
93
+ ]);
94
+ skeleton.callGasLimit = BigInt(est.callGasLimit);
95
+ skeleton.verificationGasLimit = BigInt(est.verificationGasLimit);
96
+ skeleton.preVerificationGas = BigInt(est.preVerificationGas);
97
+ skeleton.maxFeePerGas = BigInt(gasPrice.fast.maxFeePerGas);
98
+ skeleton.maxPriorityFeePerGas = BigInt(gasPrice.fast.maxPriorityFeePerGas);
99
+ skeleton.paymasterVerificationGasLimit = est.paymasterVerificationGasLimit ? BigInt(est.paymasterVerificationGasLimit) : undefined;
100
+ skeleton.paymasterPostOpGasLimit = est.paymasterPostOpGasLimit ? BigInt(est.paymasterPostOpGasLimit) : undefined;
101
+ } else {
102
+ skeleton.callGasLimit = this.gas.callGasLimit;
103
+ skeleton.verificationGasLimit = this.gas.verificationGasLimit;
104
+ skeleton.preVerificationGas = this.gas.preVerificationGas;
105
+ skeleton.maxFeePerGas = this.gas.maxFeePerGas;
106
+ skeleton.maxPriorityFeePerGas = this.gas.maxPriorityFeePerGas;
107
+ skeleton.paymasterVerificationGasLimit = this.gas.paymasterVerificationGasLimit;
108
+ skeleton.paymasterPostOpGasLimit = this.gas.paymasterPostOpGasLimit;
109
+ }
110
+ return skeleton;
111
+ }
112
+ }
113
+ // src/bundlerClient.ts
114
+ import { http, toHex } from "viem";
115
+ import { createBundlerClient as createViemBundlerClient } from "viem/account-abstraction";
116
+
117
+ class BundlerClient {
118
+ entryPoint;
119
+ client;
120
+ constructor(bundlerUrl, entryPoint) {
121
+ this.entryPoint = entryPoint;
122
+ this.client = createViemBundlerClient({ transport: http(bundlerUrl) });
123
+ }
124
+ async estimateUserOperationGas(op) {
125
+ this.client.estimateUserOperationGas;
126
+ return this.client.request({
127
+ method: "eth_estimateUserOperationGas",
128
+ params: [
129
+ {
130
+ sender: op.sender,
131
+ nonce: toHex(op.nonce),
132
+ callData: op.callData,
133
+ callGasLimit: toHex(0),
134
+ verificationGasLimit: toHex(0),
135
+ preVerificationGas: toHex(0),
136
+ maxFeePerGas: toHex(0),
137
+ maxPriorityFeePerGas: toHex(0),
138
+ paymaster: op.paymaster,
139
+ paymasterVerificationGasLimit: op.paymaster ? toHex(0) : undefined,
140
+ paymasterPostOpGasLimit: op.paymaster ? toHex(0) : undefined,
141
+ paymasterData: op.paymasterData,
142
+ signature: op.signature,
143
+ eip7702Auth: op.authorization ? serializeAuth(op.authorization) : undefined
144
+ },
145
+ this.entryPoint
146
+ ]
147
+ });
148
+ }
149
+ async getUserOperationGasPrice() {
150
+ const result = await this.client.request({
151
+ method: "pimlico_getUserOperationGasPrice",
152
+ params: []
153
+ });
154
+ const parse = (tier) => ({
155
+ maxFeePerGas: BigInt(tier.maxFeePerGas),
156
+ maxPriorityFeePerGas: BigInt(tier.maxPriorityFeePerGas)
157
+ });
158
+ return {
159
+ slow: parse(result.slow),
160
+ standard: parse(result.standard),
161
+ fast: parse(result.fast)
162
+ };
163
+ }
164
+ async sendUserOperation(op) {
165
+ return this.client.request({
166
+ method: "eth_sendUserOperation",
167
+ params: [
168
+ {
169
+ sender: op.sender,
170
+ nonce: toHex(op.nonce),
171
+ callData: op.callData,
172
+ callGasLimit: toHex(op.callGasLimit),
173
+ verificationGasLimit: toHex(op.verificationGasLimit),
174
+ preVerificationGas: toHex(op.preVerificationGas),
175
+ maxFeePerGas: toHex(op.maxFeePerGas),
176
+ maxPriorityFeePerGas: toHex(op.maxPriorityFeePerGas),
177
+ paymaster: op.paymaster,
178
+ paymasterVerificationGasLimit: op.paymasterVerificationGasLimit ? toHex(op.paymasterVerificationGasLimit) : undefined,
179
+ paymasterPostOpGasLimit: op.paymasterPostOpGasLimit ? toHex(op.paymasterPostOpGasLimit) : undefined,
180
+ paymasterData: op.paymasterData,
181
+ signature: op.signature,
182
+ eip7702Auth: op.authorization ? serializeAuth(op.authorization) : undefined
183
+ },
184
+ this.entryPoint
185
+ ]
186
+ });
187
+ }
188
+ async waitForUserOperationReceipt(hash) {
189
+ return this.client.waitForUserOperationReceipt({ hash });
190
+ }
191
+ }
192
+ function serializeAuth(auth) {
193
+ return {
194
+ address: auth.address,
195
+ chainId: toHex(auth.chainId),
196
+ nonce: toHex(auth.nonce),
197
+ r: auth.r,
198
+ s: auth.s,
199
+ yParity: toHex(auth.yParity)
200
+ };
201
+ }
202
+ // src/privacyProtocolBuilder.ts
203
+ import { encodeFunctionData } from "viem";
204
+ var privacyAccountAbi = [
205
+ {
206
+ type: "function",
207
+ name: "execute",
208
+ inputs: [
209
+ { name: "feeCalldata", type: "bytes" },
210
+ {
211
+ name: "tail",
212
+ type: "tuple[]",
213
+ components: [
214
+ { name: "target", type: "address" },
215
+ { name: "data", type: "bytes" }
216
+ ]
217
+ }
218
+ ],
219
+ outputs: [],
220
+ stateMutability: "nonpayable"
221
+ }
222
+ ];
223
+
224
+ class PrivacyProtocolBuilder extends UserOperationBuilder {
225
+ feeCalldata = "0x";
226
+ tail = [];
227
+ constructor(sender) {
228
+ super(sender);
229
+ }
230
+ withFeeCalldata(calldata) {
231
+ this.feeCalldata = calldata;
232
+ const cd = encodeFunctionData({
233
+ abi: privacyAccountAbi,
234
+ functionName: "execute",
235
+ args: [this.feeCalldata, this.tail]
236
+ });
237
+ return this.withCalldata(cd);
238
+ }
239
+ withTailCall(target, data) {
240
+ this.tail.push({ target, data });
241
+ const cd = encodeFunctionData({
242
+ abi: privacyAccountAbi,
243
+ functionName: "execute",
244
+ args: [this.feeCalldata, this.tail]
245
+ });
246
+ return this.withCalldata(cd);
247
+ }
248
+ }
249
+ // src/tornadoBuilder.ts
250
+ import { encodeFunctionData as encodeFunctionData2, parseAbi } from "viem";
251
+ var tornadoAbi = parseAbi([
252
+ "function withdraw(bytes proof, bytes32 root, bytes32 nullifierHash, address recipient, address relayer, uint256 fee, uint256 refund)"
253
+ ]);
254
+
255
+ class TornadoBuilder extends PrivacyProtocolBuilder {
256
+ constructor(sender) {
257
+ super(sender);
258
+ }
259
+ withWithdraw(proof, root, nullifierHash, recipient, relayer, fee) {
260
+ const calldata = encodeFunctionData2({
261
+ abi: tornadoAbi,
262
+ functionName: "withdraw",
263
+ args: [proof, root, nullifierHash, recipient, relayer, fee, 0n]
264
+ });
265
+ return this.withFeeCalldata(calldata);
266
+ }
267
+ }
268
+ export {
269
+ tornadoAbi,
270
+ UserOperationBuilder,
271
+ TornadoBuilder,
272
+ PrivacyProtocolBuilder,
273
+ BundlerClient
274
+ };
@@ -0,0 +1,26 @@
1
+ import { type Address, type Hex, type SignedAuthorization } from 'viem';
2
+ import type { UserOperation } from 'viem';
3
+ import type { EIP1193Provider, GasConfig } from './types.js';
4
+ import type { BundlerClient } from './bundlerClient.js';
5
+ export declare class UserOperationBuilder {
6
+ private sender;
7
+ private calldata;
8
+ private authorization?;
9
+ private paymaster?;
10
+ private paymasterData?;
11
+ private signature;
12
+ private nonceKey;
13
+ private gas;
14
+ private factory?;
15
+ private factoryData?;
16
+ constructor(sender: Address);
17
+ withCalldata(calldata: Hex): this;
18
+ withPaymaster(paymaster: Address): this;
19
+ withPaymasterData(data: Hex): this;
20
+ withSignature(signature: Hex): this;
21
+ withNonceKey(key: bigint): this;
22
+ withGas(gas: GasConfig): this;
23
+ withFactory(factory: Address, factoryData: Hex): this;
24
+ withAuthorization(auth: SignedAuthorization<number>): this;
25
+ build(provider: EIP1193Provider, bundlerClient: BundlerClient): Promise<UserOperation>;
26
+ }
@@ -0,0 +1,20 @@
1
+ import { type Address, type EstimateUserOperationGasReturnType, type Hash } from "viem";
2
+ import type { UserOperation, UserOperationReceipt } from "viem/account-abstraction";
3
+ export type UserOperationGasPrice = {
4
+ slow: GasPrice;
5
+ standard: GasPrice;
6
+ fast: GasPrice;
7
+ };
8
+ export type GasPrice = {
9
+ maxFeePerGas: bigint;
10
+ maxPriorityFeePerGas: bigint;
11
+ };
12
+ export declare class BundlerClient {
13
+ entryPoint: Address;
14
+ private client;
15
+ constructor(bundlerUrl: string, entryPoint: Address);
16
+ estimateUserOperationGas(op: UserOperation): Promise<EstimateUserOperationGasReturnType>;
17
+ getUserOperationGasPrice(): Promise<UserOperationGasPrice>;
18
+ sendUserOperation(op: UserOperation): Promise<Hash>;
19
+ waitForUserOperationReceipt(hash: Hash): Promise<UserOperationReceipt>;
20
+ }
@@ -0,0 +1,9 @@
1
+ import { type Address, type Hex } from "viem";
2
+ import { UserOperationBuilder } from "./builder.js";
3
+ export declare class PrivacyProtocolBuilder extends UserOperationBuilder {
4
+ private feeCalldata;
5
+ private tail;
6
+ constructor(sender: Address);
7
+ withFeeCalldata(calldata: Hex): this;
8
+ withTailCall(target: Address, data: Hex): this;
9
+ }
@@ -0,0 +1,34 @@
1
+ import { type Address, type Hex } from "viem";
2
+ import { PrivacyProtocolBuilder } from "./privacyProtocolBuilder.js";
3
+ export declare const tornadoAbi: readonly [{
4
+ readonly name: "withdraw";
5
+ readonly type: "function";
6
+ readonly stateMutability: "nonpayable";
7
+ readonly inputs: readonly [{
8
+ readonly type: "bytes";
9
+ readonly name: "proof";
10
+ }, {
11
+ readonly type: "bytes32";
12
+ readonly name: "root";
13
+ }, {
14
+ readonly type: "bytes32";
15
+ readonly name: "nullifierHash";
16
+ }, {
17
+ readonly type: "address";
18
+ readonly name: "recipient";
19
+ }, {
20
+ readonly type: "address";
21
+ readonly name: "relayer";
22
+ }, {
23
+ readonly type: "uint256";
24
+ readonly name: "fee";
25
+ }, {
26
+ readonly type: "uint256";
27
+ readonly name: "refund";
28
+ }];
29
+ readonly outputs: readonly [];
30
+ }];
31
+ export declare class TornadoBuilder extends PrivacyProtocolBuilder {
32
+ constructor(sender: Address);
33
+ withWithdraw(proof: Hex, root: Hex, nullifierHash: Hex, recipient: Address, relayer: Address, fee: bigint): this;
34
+ }
@@ -0,0 +1,18 @@
1
+ export interface EIP1193Provider {
2
+ request(args: {
3
+ method: string;
4
+ params?: unknown;
5
+ }): Promise<unknown>;
6
+ }
7
+ export type GasConfig = {
8
+ type: 'auto';
9
+ } | {
10
+ type: 'manual';
11
+ callGasLimit: bigint;
12
+ verificationGasLimit: bigint;
13
+ preVerificationGas: bigint;
14
+ maxFeePerGas: bigint;
15
+ maxPriorityFeePerGas: bigint;
16
+ paymasterVerificationGasLimit?: bigint;
17
+ paymasterPostOpGasLimit?: bigint;
18
+ };
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@privacy-paymasters/sdk",
3
+ "module": "dist/index.js",
4
+ "types": "dist/index.d.ts",
5
+ "type": "module",
6
+ "version": "0.0.1",
7
+ "private": false,
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "devDependencies": {
18
+ "@types/bun": "latest"
19
+ },
20
+ "peerDependencies": {
21
+ "typescript": "^5.9.0"
22
+ },
23
+ "scripts": {
24
+ "build": "bun build ./index.ts --outdir ./dist --target node --format esm --packages external && tsc -p tsconfig.build.json",
25
+ "test": "bun test",
26
+ "test:e2e": "bun test tests/e2e.test.ts"
27
+ },
28
+ "dependencies": {
29
+ "@pimlico/alto": "^0.0.20",
30
+ "prool": "^0.2.4",
31
+ "smol-toml": "^1.6.1",
32
+ "viem": "2.48.4"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public",
36
+ "registry": "https://registry.npmjs.org"
37
+ }
38
+ }