near-safe 0.9.8 → 0.9.10

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.
@@ -1,5 +1,6 @@
1
1
  import { Address, Hash, PublicClient, Transport } from "viem";
2
2
  import { GasPrices, PaymasterData, SponsorshipPolicyData, UnsignedUserOperation, UserOperation, UserOperationGas, UserOperationReceipt } from "../types";
3
+ import { Pimlico } from "./pimlico";
3
4
  type SponsorshipPolicy = {
4
5
  sponsorshipPolicyId: string;
5
6
  };
@@ -33,15 +34,14 @@ type BundlerRpcSchema = [
33
34
  export declare class Erc4337Bundler {
34
35
  client: PublicClient<Transport, undefined, undefined, BundlerRpcSchema>;
35
36
  entryPointAddress: Address;
36
- apiKey: string;
37
+ pimlico: Pimlico;
37
38
  chainId: number;
38
39
  constructor(entryPointAddress: Address, apiKey: string, chainId: number);
39
40
  getPaymasterData(rawUserOp: UnsignedUserOperation, sponsorshipPolicy?: string): Promise<PaymasterData>;
40
41
  sendUserOperation(userOp: UserOperation): Promise<Hash>;
41
42
  getGasPrice(): Promise<GasPrices>;
42
43
  getUserOpReceipt(userOpHash: Hash): Promise<UserOperationReceipt>;
43
- private _getUserOpReceiptInner;
44
44
  getSponsorshipPolicies(): Promise<SponsorshipPolicyData[]>;
45
+ private _getUserOpReceiptInner;
45
46
  }
46
- export declare function stripApiKey(error: unknown): string;
47
47
  export {};
@@ -1,19 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Erc4337Bundler = void 0;
4
- exports.stripApiKey = stripApiKey;
5
4
  const viem_1 = require("viem");
6
5
  const util_1 = require("../util");
7
- function bundlerUrl(chainId, apikey) {
8
- return `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${apikey}`;
9
- }
6
+ const pimlico_1 = require("./pimlico");
10
7
  class Erc4337Bundler {
11
8
  constructor(entryPointAddress, apiKey, chainId) {
12
9
  this.entryPointAddress = entryPointAddress;
13
- this.apiKey = apiKey;
10
+ this.pimlico = new pimlico_1.Pimlico(apiKey);
14
11
  this.chainId = chainId;
15
12
  this.client = (0, viem_1.createPublicClient)({
16
- transport: (0, viem_1.http)(bundlerUrl(chainId, this.apiKey)),
13
+ transport: (0, viem_1.http)(this.pimlico.bundlerUrl(chainId)),
17
14
  rpcSchema: (0, viem_1.rpcSchema)(),
18
15
  });
19
16
  }
@@ -21,7 +18,7 @@ class Erc4337Bundler {
21
18
  const userOp = { ...rawUserOp, signature: util_1.PLACEHOLDER_SIG };
22
19
  if (sponsorshipPolicy) {
23
20
  console.log("Requesting paymaster data...");
24
- return handleRequest(() => this.client.request({
21
+ return this.pimlico.handleRequest(() => this.client.request({
25
22
  method: "pm_sponsorUserOperation",
26
23
  params: [
27
24
  userOp,
@@ -31,20 +28,20 @@ class Erc4337Bundler {
31
28
  }));
32
29
  }
33
30
  console.log("Estimating user operation gas...");
34
- return handleRequest(() => this.client.request({
31
+ return this.pimlico.handleRequest(() => this.client.request({
35
32
  method: "eth_estimateUserOperationGas",
36
33
  params: [userOp, this.entryPointAddress],
37
34
  }));
38
35
  }
39
36
  async sendUserOperation(userOp) {
40
- return handleRequest(() => this.client.request({
37
+ return this.pimlico.handleRequest(() => this.client.request({
41
38
  method: "eth_sendUserOperation",
42
39
  params: [userOp, this.entryPointAddress],
43
40
  }));
44
41
  // throw new Error(`Failed to send user op with: ${error.message}`);
45
42
  }
46
43
  async getGasPrice() {
47
- return handleRequest(() => this.client.request({
44
+ return this.pimlico.handleRequest(() => this.client.request({
48
45
  method: "pimlico_getUserOperationGasPrice",
49
46
  params: [],
50
47
  }));
@@ -58,52 +55,16 @@ class Erc4337Bundler {
58
55
  }
59
56
  return userOpReceipt;
60
57
  }
58
+ async getSponsorshipPolicies() {
59
+ // Chain ID doesn't matter for this bundler endpoint.
60
+ const allPolicies = await this.pimlico.getSponsorshipPolicies();
61
+ return allPolicies.filter((p) => p.chain_ids.allowlist.includes(this.chainId));
62
+ }
61
63
  async _getUserOpReceiptInner(userOpHash) {
62
- return handleRequest(() => this.client.request({
64
+ return this.pimlico.handleRequest(() => this.client.request({
63
65
  method: "eth_getUserOperationReceipt",
64
66
  params: [userOpHash],
65
67
  }));
66
68
  }
67
- // New method to query sponsorship policies
68
- async getSponsorshipPolicies() {
69
- const url = `https://api.pimlico.io/v2/account/sponsorship_policies?apikey=${this.apiKey}`;
70
- const allPolocies = await handleRequest(async () => {
71
- const response = await fetch(url);
72
- if (!response.ok) {
73
- throw new Error(`HTTP error! status: ${response.status}: ${response.statusText}`);
74
- }
75
- return response.json();
76
- });
77
- return allPolocies.data.filter((p) => p.chain_ids.allowlist.includes(this.chainId));
78
- }
79
69
  }
80
70
  exports.Erc4337Bundler = Erc4337Bundler;
81
- async function handleRequest(clientMethod) {
82
- try {
83
- return await clientMethod();
84
- }
85
- catch (error) {
86
- const message = stripApiKey(error);
87
- if (error instanceof viem_1.HttpRequestError) {
88
- if (error.status === 401) {
89
- throw new Error("Unauthorized request. Please check your Pimlico API key.");
90
- }
91
- else {
92
- throw new Error(`Pimlico: ${message}`);
93
- }
94
- }
95
- else if (error instanceof viem_1.RpcError) {
96
- throw new Error(`Failed to send user op with: ${message}`);
97
- }
98
- throw new Error(`Bundler Request: ${message}`);
99
- }
100
- }
101
- function stripApiKey(error) {
102
- const message = error instanceof Error ? error.message : String(error);
103
- return message.replace(/(apikey=)[^\s&]+/, "$1***");
104
- // Could also do this with slicing.
105
- // const keyStart = message.indexOf("apikey=") + 7;
106
- // // If no apikey in the message, return it as is.
107
- // if (keyStart === -1) return message;
108
- // return `${message.slice(0, keyStart)}***${message.slice(keyStart + 36)}`;
109
- }
@@ -0,0 +1,11 @@
1
+ import { SponsorshipPolicyData } from "../types";
2
+ export declare class Pimlico {
3
+ private apiKey;
4
+ constructor(apiKey: string);
5
+ bundlerUrl(chainId: number): string;
6
+ getSponsorshipPolicies(): Promise<SponsorshipPolicyData[]>;
7
+ getSponsorshipPolicyByName(name: string): Promise<SponsorshipPolicyData>;
8
+ getSponsorshipPolicyById(id: string): Promise<SponsorshipPolicyData>;
9
+ handleRequest<T>(clientMethod: () => Promise<T>): Promise<T>;
10
+ }
11
+ export declare function stripApiKey(error: unknown): string;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Pimlico = void 0;
4
+ exports.stripApiKey = stripApiKey;
5
+ const viem_1 = require("viem");
6
+ class Pimlico {
7
+ constructor(apiKey) {
8
+ this.apiKey = apiKey;
9
+ }
10
+ bundlerUrl(chainId) {
11
+ return `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${this.apiKey}`;
12
+ }
13
+ // New method to query sponsorship policies
14
+ async getSponsorshipPolicies() {
15
+ const url = `https://api.pimlico.io/v2/account/sponsorship_policies?apikey=${this.apiKey}`;
16
+ const allPolicies = await this.handleRequest(async () => {
17
+ const response = await fetch(url);
18
+ if (!response.ok) {
19
+ throw new Error(`HTTP error! status: ${response.status}: ${response.statusText}`);
20
+ }
21
+ return response.json();
22
+ });
23
+ return allPolicies.data;
24
+ }
25
+ async getSponsorshipPolicyByName(name) {
26
+ const allPolicies = await this.getSponsorshipPolicies();
27
+ const result = allPolicies.filter((t) => t.policy_name === name);
28
+ if (result.length === 0) {
29
+ throw new Error(`No policy found with policy_name=${name}: try ${allPolicies.map((t) => t.policy_name)}`);
30
+ }
31
+ else if (result.length > 1) {
32
+ throw new Error(`Multiple Policies with same policy_name=${name}: ${JSON.stringify(result)}`);
33
+ }
34
+ return result[0];
35
+ }
36
+ async getSponsorshipPolicyById(id) {
37
+ const allPolicies = await this.getSponsorshipPolicies();
38
+ const result = allPolicies.filter((t) => t.id === id);
39
+ if (result.length === 0) {
40
+ throw new Error(`No policy found with id=${id}: try ${allPolicies.map((t) => t.id)}`);
41
+ }
42
+ // We assume that ids are unique so that result.length > 1 need not be handled.
43
+ return result[0];
44
+ }
45
+ async handleRequest(clientMethod) {
46
+ try {
47
+ return await clientMethod();
48
+ }
49
+ catch (error) {
50
+ const message = stripApiKey(error);
51
+ if (error instanceof viem_1.HttpRequestError) {
52
+ if (error.status === 401) {
53
+ throw new Error("Unauthorized request. Please check your Pimlico API key.");
54
+ }
55
+ else {
56
+ throw new Error(`Pimlico: ${message}`);
57
+ }
58
+ }
59
+ else if (error instanceof viem_1.RpcError) {
60
+ throw new Error(`Failed to send user op with: ${message}`);
61
+ }
62
+ throw new Error(`Bundler Request: ${message}`);
63
+ }
64
+ }
65
+ }
66
+ exports.Pimlico = Pimlico;
67
+ function stripApiKey(error) {
68
+ const message = error instanceof Error ? error.message : String(error);
69
+ return message.replace(/(apikey=)[^\s&]+/, "$1***");
70
+ // Could also do this with slicing.
71
+ // const keyStart = message.indexOf("apikey=") + 7;
72
+ // // If no apikey in the message, return it as is.
73
+ // if (keyStart === -1) return message;
74
+ // return `${message.slice(0, keyStart)}***${message.slice(keyStart + 36)}`;
75
+ }
@@ -169,7 +169,7 @@ export declare class NearSafe {
169
169
  */
170
170
  requestRouter({ method, chainId, params }: SignRequestData, sponsorshipPolicy?: string): Promise<EncodedSignRequest>;
171
171
  encodeForSafe(from: string): boolean;
172
- policyForChainId(chainId: number): Promise<SponsorshipPolicyData[]>;
172
+ policiesForChainId(chainId: number): Promise<SponsorshipPolicyData[]>;
173
173
  deploymentRequest(chainId: number): SignRequestData;
174
174
  addOwnerRequest(chainId: number, recoveryAddress: Address): SignRequestData;
175
175
  }
@@ -346,9 +346,8 @@ class NearSafe {
346
346
  }
347
347
  return [this.address.toLowerCase(), lowerZero].includes(lowerFrom);
348
348
  }
349
- async policyForChainId(chainId) {
350
- const bundler = this.bundlerForChainId(chainId);
351
- return bundler.getSponsorshipPolicies();
349
+ async policiesForChainId(chainId) {
350
+ return this.bundlerForChainId(chainId).getSponsorshipPolicies();
352
351
  }
353
352
  deploymentRequest(chainId) {
354
353
  return {
@@ -1,5 +1,6 @@
1
1
  import { Address, Hash, PublicClient, Transport } from "viem";
2
2
  import { GasPrices, PaymasterData, SponsorshipPolicyData, UnsignedUserOperation, UserOperation, UserOperationGas, UserOperationReceipt } from "../types";
3
+ import { Pimlico } from "./pimlico";
3
4
  type SponsorshipPolicy = {
4
5
  sponsorshipPolicyId: string;
5
6
  };
@@ -33,15 +34,14 @@ type BundlerRpcSchema = [
33
34
  export declare class Erc4337Bundler {
34
35
  client: PublicClient<Transport, undefined, undefined, BundlerRpcSchema>;
35
36
  entryPointAddress: Address;
36
- apiKey: string;
37
+ pimlico: Pimlico;
37
38
  chainId: number;
38
39
  constructor(entryPointAddress: Address, apiKey: string, chainId: number);
39
40
  getPaymasterData(rawUserOp: UnsignedUserOperation, sponsorshipPolicy?: string): Promise<PaymasterData>;
40
41
  sendUserOperation(userOp: UserOperation): Promise<Hash>;
41
42
  getGasPrice(): Promise<GasPrices>;
42
43
  getUserOpReceipt(userOpHash: Hash): Promise<UserOperationReceipt>;
43
- private _getUserOpReceiptInner;
44
44
  getSponsorshipPolicies(): Promise<SponsorshipPolicyData[]>;
45
+ private _getUserOpReceiptInner;
45
46
  }
46
- export declare function stripApiKey(error: unknown): string;
47
47
  export {};
@@ -1,19 +1,17 @@
1
- import { createPublicClient, http, rpcSchema, RpcError, HttpRequestError, } from "viem";
1
+ import { createPublicClient, http, rpcSchema, } from "viem";
2
2
  import { PLACEHOLDER_SIG } from "../util";
3
- function bundlerUrl(chainId, apikey) {
4
- return `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${apikey}`;
5
- }
3
+ import { Pimlico } from "./pimlico";
6
4
  export class Erc4337Bundler {
7
5
  client;
8
6
  entryPointAddress;
9
- apiKey;
7
+ pimlico;
10
8
  chainId;
11
9
  constructor(entryPointAddress, apiKey, chainId) {
12
10
  this.entryPointAddress = entryPointAddress;
13
- this.apiKey = apiKey;
11
+ this.pimlico = new Pimlico(apiKey);
14
12
  this.chainId = chainId;
15
13
  this.client = createPublicClient({
16
- transport: http(bundlerUrl(chainId, this.apiKey)),
14
+ transport: http(this.pimlico.bundlerUrl(chainId)),
17
15
  rpcSchema: rpcSchema(),
18
16
  });
19
17
  }
@@ -21,7 +19,7 @@ export class Erc4337Bundler {
21
19
  const userOp = { ...rawUserOp, signature: PLACEHOLDER_SIG };
22
20
  if (sponsorshipPolicy) {
23
21
  console.log("Requesting paymaster data...");
24
- return handleRequest(() => this.client.request({
22
+ return this.pimlico.handleRequest(() => this.client.request({
25
23
  method: "pm_sponsorUserOperation",
26
24
  params: [
27
25
  userOp,
@@ -31,20 +29,20 @@ export class Erc4337Bundler {
31
29
  }));
32
30
  }
33
31
  console.log("Estimating user operation gas...");
34
- return handleRequest(() => this.client.request({
32
+ return this.pimlico.handleRequest(() => this.client.request({
35
33
  method: "eth_estimateUserOperationGas",
36
34
  params: [userOp, this.entryPointAddress],
37
35
  }));
38
36
  }
39
37
  async sendUserOperation(userOp) {
40
- return handleRequest(() => this.client.request({
38
+ return this.pimlico.handleRequest(() => this.client.request({
41
39
  method: "eth_sendUserOperation",
42
40
  params: [userOp, this.entryPointAddress],
43
41
  }));
44
42
  // throw new Error(`Failed to send user op with: ${error.message}`);
45
43
  }
46
44
  async getGasPrice() {
47
- return handleRequest(() => this.client.request({
45
+ return this.pimlico.handleRequest(() => this.client.request({
48
46
  method: "pimlico_getUserOperationGasPrice",
49
47
  params: [],
50
48
  }));
@@ -58,51 +56,15 @@ export class Erc4337Bundler {
58
56
  }
59
57
  return userOpReceipt;
60
58
  }
59
+ async getSponsorshipPolicies() {
60
+ // Chain ID doesn't matter for this bundler endpoint.
61
+ const allPolicies = await this.pimlico.getSponsorshipPolicies();
62
+ return allPolicies.filter((p) => p.chain_ids.allowlist.includes(this.chainId));
63
+ }
61
64
  async _getUserOpReceiptInner(userOpHash) {
62
- return handleRequest(() => this.client.request({
65
+ return this.pimlico.handleRequest(() => this.client.request({
63
66
  method: "eth_getUserOperationReceipt",
64
67
  params: [userOpHash],
65
68
  }));
66
69
  }
67
- // New method to query sponsorship policies
68
- async getSponsorshipPolicies() {
69
- const url = `https://api.pimlico.io/v2/account/sponsorship_policies?apikey=${this.apiKey}`;
70
- const allPolocies = await handleRequest(async () => {
71
- const response = await fetch(url);
72
- if (!response.ok) {
73
- throw new Error(`HTTP error! status: ${response.status}: ${response.statusText}`);
74
- }
75
- return response.json();
76
- });
77
- return allPolocies.data.filter((p) => p.chain_ids.allowlist.includes(this.chainId));
78
- }
79
- }
80
- async function handleRequest(clientMethod) {
81
- try {
82
- return await clientMethod();
83
- }
84
- catch (error) {
85
- const message = stripApiKey(error);
86
- if (error instanceof HttpRequestError) {
87
- if (error.status === 401) {
88
- throw new Error("Unauthorized request. Please check your Pimlico API key.");
89
- }
90
- else {
91
- throw new Error(`Pimlico: ${message}`);
92
- }
93
- }
94
- else if (error instanceof RpcError) {
95
- throw new Error(`Failed to send user op with: ${message}`);
96
- }
97
- throw new Error(`Bundler Request: ${message}`);
98
- }
99
- }
100
- export function stripApiKey(error) {
101
- const message = error instanceof Error ? error.message : String(error);
102
- return message.replace(/(apikey=)[^\s&]+/, "$1***");
103
- // Could also do this with slicing.
104
- // const keyStart = message.indexOf("apikey=") + 7;
105
- // // If no apikey in the message, return it as is.
106
- // if (keyStart === -1) return message;
107
- // return `${message.slice(0, keyStart)}***${message.slice(keyStart + 36)}`;
108
70
  }
@@ -0,0 +1,11 @@
1
+ import { SponsorshipPolicyData } from "../types";
2
+ export declare class Pimlico {
3
+ private apiKey;
4
+ constructor(apiKey: string);
5
+ bundlerUrl(chainId: number): string;
6
+ getSponsorshipPolicies(): Promise<SponsorshipPolicyData[]>;
7
+ getSponsorshipPolicyByName(name: string): Promise<SponsorshipPolicyData>;
8
+ getSponsorshipPolicyById(id: string): Promise<SponsorshipPolicyData>;
9
+ handleRequest<T>(clientMethod: () => Promise<T>): Promise<T>;
10
+ }
11
+ export declare function stripApiKey(error: unknown): string;
@@ -0,0 +1,71 @@
1
+ import { HttpRequestError, RpcError } from "viem";
2
+ export class Pimlico {
3
+ apiKey;
4
+ constructor(apiKey) {
5
+ this.apiKey = apiKey;
6
+ }
7
+ bundlerUrl(chainId) {
8
+ return `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${this.apiKey}`;
9
+ }
10
+ // New method to query sponsorship policies
11
+ async getSponsorshipPolicies() {
12
+ const url = `https://api.pimlico.io/v2/account/sponsorship_policies?apikey=${this.apiKey}`;
13
+ const allPolicies = await this.handleRequest(async () => {
14
+ const response = await fetch(url);
15
+ if (!response.ok) {
16
+ throw new Error(`HTTP error! status: ${response.status}: ${response.statusText}`);
17
+ }
18
+ return response.json();
19
+ });
20
+ return allPolicies.data;
21
+ }
22
+ async getSponsorshipPolicyByName(name) {
23
+ const allPolicies = await this.getSponsorshipPolicies();
24
+ const result = allPolicies.filter((t) => t.policy_name === name);
25
+ if (result.length === 0) {
26
+ throw new Error(`No policy found with policy_name=${name}: try ${allPolicies.map((t) => t.policy_name)}`);
27
+ }
28
+ else if (result.length > 1) {
29
+ throw new Error(`Multiple Policies with same policy_name=${name}: ${JSON.stringify(result)}`);
30
+ }
31
+ return result[0];
32
+ }
33
+ async getSponsorshipPolicyById(id) {
34
+ const allPolicies = await this.getSponsorshipPolicies();
35
+ const result = allPolicies.filter((t) => t.id === id);
36
+ if (result.length === 0) {
37
+ throw new Error(`No policy found with id=${id}: try ${allPolicies.map((t) => t.id)}`);
38
+ }
39
+ // We assume that ids are unique so that result.length > 1 need not be handled.
40
+ return result[0];
41
+ }
42
+ async handleRequest(clientMethod) {
43
+ try {
44
+ return await clientMethod();
45
+ }
46
+ catch (error) {
47
+ const message = stripApiKey(error);
48
+ if (error instanceof HttpRequestError) {
49
+ if (error.status === 401) {
50
+ throw new Error("Unauthorized request. Please check your Pimlico API key.");
51
+ }
52
+ else {
53
+ throw new Error(`Pimlico: ${message}`);
54
+ }
55
+ }
56
+ else if (error instanceof RpcError) {
57
+ throw new Error(`Failed to send user op with: ${message}`);
58
+ }
59
+ throw new Error(`Bundler Request: ${message}`);
60
+ }
61
+ }
62
+ }
63
+ export function stripApiKey(error) {
64
+ const message = error instanceof Error ? error.message : String(error);
65
+ return message.replace(/(apikey=)[^\s&]+/, "$1***");
66
+ // Could also do this with slicing.
67
+ // const keyStart = message.indexOf("apikey=") + 7;
68
+ // // If no apikey in the message, return it as is.
69
+ // if (keyStart === -1) return message;
70
+ // return `${message.slice(0, keyStart)}***${message.slice(keyStart + 36)}`;
71
+ }
@@ -169,7 +169,7 @@ export declare class NearSafe {
169
169
  */
170
170
  requestRouter({ method, chainId, params }: SignRequestData, sponsorshipPolicy?: string): Promise<EncodedSignRequest>;
171
171
  encodeForSafe(from: string): boolean;
172
- policyForChainId(chainId: number): Promise<SponsorshipPolicyData[]>;
172
+ policiesForChainId(chainId: number): Promise<SponsorshipPolicyData[]>;
173
173
  deploymentRequest(chainId: number): SignRequestData;
174
174
  addOwnerRequest(chainId: number, recoveryAddress: Address): SignRequestData;
175
175
  }
@@ -349,9 +349,8 @@ export class NearSafe {
349
349
  }
350
350
  return [this.address.toLowerCase(), lowerZero].includes(lowerFrom);
351
351
  }
352
- async policyForChainId(chainId) {
353
- const bundler = this.bundlerForChainId(chainId);
354
- return bundler.getSponsorshipPolicies();
352
+ async policiesForChainId(chainId) {
353
+ return this.bundlerForChainId(chainId).getSponsorshipPolicies();
355
354
  }
356
355
  deploymentRequest(chainId) {
357
356
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "near-safe",
3
- "version": "0.9.8",
3
+ "version": "0.9.10",
4
4
  "license": "MIT",
5
5
  "description": "An SDK for controlling Ethereum Smart Accounts via ERC4337 from a Near Account.",
6
6
  "author": "bh2smith",