@aastar/paymaster 0.16.7

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 (106) hide show
  1. package/LICENSE +21 -0
  2. package/dist/core/src/abis/BLSAggregator.json +686 -0
  3. package/dist/core/src/abis/BLSValidator.json +42 -0
  4. package/dist/core/src/abis/DVTValidator.json +368 -0
  5. package/dist/core/src/abis/EntryPoint.json +1382 -0
  6. package/dist/core/src/abis/GToken.json +513 -0
  7. package/dist/core/src/abis/GTokenStaking.json +949 -0
  8. package/dist/core/src/abis/MySBT.json +1518 -0
  9. package/dist/core/src/abis/Paymaster.json +1143 -0
  10. package/dist/core/src/abis/PaymasterFactory.json +640 -0
  11. package/dist/core/src/abis/Registry.json +1942 -0
  12. package/dist/core/src/abis/ReputationSystem.json +699 -0
  13. package/dist/core/src/abis/SimpleAccount.json +560 -0
  14. package/dist/core/src/abis/SimpleAccountFactory.json +111 -0
  15. package/dist/core/src/abis/SuperPaymaster.json +1781 -0
  16. package/dist/core/src/abis/index.d.ts +1126 -0
  17. package/dist/core/src/abis/index.js +91 -0
  18. package/dist/core/src/abis/xPNTsFactory.json +718 -0
  19. package/dist/core/src/abis/xPNTsToken.json +1280 -0
  20. package/dist/core/src/actions/StateValidator.d.ts +68 -0
  21. package/dist/core/src/actions/StateValidator.js +187 -0
  22. package/dist/core/src/actions/account.d.ts +55 -0
  23. package/dist/core/src/actions/account.js +133 -0
  24. package/dist/core/src/actions/aggregator.d.ts +17 -0
  25. package/dist/core/src/actions/aggregator.js +31 -0
  26. package/dist/core/src/actions/dvt.d.ts +30 -0
  27. package/dist/core/src/actions/dvt.js +41 -0
  28. package/dist/core/src/actions/entryPoint.d.ts +90 -0
  29. package/dist/core/src/actions/entryPoint.js +211 -0
  30. package/dist/core/src/actions/factory.d.ts +215 -0
  31. package/dist/core/src/actions/factory.js +442 -0
  32. package/dist/core/src/actions/faucet.d.ts +48 -0
  33. package/dist/core/src/actions/faucet.js +337 -0
  34. package/dist/core/src/actions/gtokenExtended.d.ts +39 -0
  35. package/dist/core/src/actions/gtokenExtended.js +115 -0
  36. package/dist/core/src/actions/index.d.ts +15 -0
  37. package/dist/core/src/actions/index.js +17 -0
  38. package/dist/core/src/actions/paymasterV4.d.ts +170 -0
  39. package/dist/core/src/actions/paymasterV4.js +334 -0
  40. package/dist/core/src/actions/registry.d.ts +246 -0
  41. package/dist/core/src/actions/registry.js +667 -0
  42. package/dist/core/src/actions/reputation.d.ts +129 -0
  43. package/dist/core/src/actions/reputation.js +281 -0
  44. package/dist/core/src/actions/sbt.d.ts +191 -0
  45. package/dist/core/src/actions/sbt.js +533 -0
  46. package/dist/core/src/actions/staking.d.ts +132 -0
  47. package/dist/core/src/actions/staking.js +330 -0
  48. package/dist/core/src/actions/superPaymaster.d.ts +237 -0
  49. package/dist/core/src/actions/superPaymaster.js +644 -0
  50. package/dist/core/src/actions/tokens.d.ts +229 -0
  51. package/dist/core/src/actions/tokens.js +415 -0
  52. package/dist/core/src/branding.d.ts +30 -0
  53. package/dist/core/src/branding.js +30 -0
  54. package/dist/core/src/clients/BaseClient.d.ts +25 -0
  55. package/dist/core/src/clients/BaseClient.js +66 -0
  56. package/dist/core/src/clients/types.d.ts +60 -0
  57. package/dist/core/src/clients/types.js +1 -0
  58. package/dist/core/src/clients.d.ts +5 -0
  59. package/dist/core/src/clients.js +11 -0
  60. package/dist/core/src/communities.d.ts +52 -0
  61. package/dist/core/src/communities.js +73 -0
  62. package/dist/core/src/config/ContractConfigManager.d.ts +20 -0
  63. package/dist/core/src/config/ContractConfigManager.js +48 -0
  64. package/dist/core/src/constants.d.ts +88 -0
  65. package/dist/core/src/constants.js +125 -0
  66. package/dist/core/src/contract-addresses.d.ts +110 -0
  67. package/dist/core/src/contract-addresses.js +99 -0
  68. package/dist/core/src/contracts.d.ts +424 -0
  69. package/dist/core/src/contracts.js +343 -0
  70. package/dist/core/src/crypto/blsSigner.d.ts +64 -0
  71. package/dist/core/src/crypto/blsSigner.js +98 -0
  72. package/dist/core/src/crypto/index.d.ts +1 -0
  73. package/dist/core/src/crypto/index.js +1 -0
  74. package/dist/core/src/index.d.ts +21 -0
  75. package/dist/core/src/index.js +21 -0
  76. package/dist/core/src/networks.d.ts +127 -0
  77. package/dist/core/src/networks.js +118 -0
  78. package/dist/core/src/requirementChecker.d.ts +38 -0
  79. package/dist/core/src/requirementChecker.js +139 -0
  80. package/dist/core/src/roles.d.ts +204 -0
  81. package/dist/core/src/roles.js +211 -0
  82. package/dist/core/src/utils/validation.d.ts +24 -0
  83. package/dist/core/src/utils/validation.js +56 -0
  84. package/dist/paymaster/src/SuperPaymaster/index.d.ts +44 -0
  85. package/dist/paymaster/src/SuperPaymaster/index.js +133 -0
  86. package/dist/paymaster/src/V4/PaymasterClient.d.ts +79 -0
  87. package/dist/paymaster/src/V4/PaymasterClient.js +315 -0
  88. package/dist/paymaster/src/V4/PaymasterClient.test.d.ts +1 -0
  89. package/dist/paymaster/src/V4/PaymasterClient.test.js +80 -0
  90. package/dist/paymaster/src/V4/PaymasterOperator.d.ts +41 -0
  91. package/dist/paymaster/src/V4/PaymasterOperator.js +241 -0
  92. package/dist/paymaster/src/V4/PaymasterOperator.test.d.ts +1 -0
  93. package/dist/paymaster/src/V4/PaymasterOperator.test.js +66 -0
  94. package/dist/paymaster/src/V4/PaymasterUtils.d.ts +55 -0
  95. package/dist/paymaster/src/V4/PaymasterUtils.js +124 -0
  96. package/dist/paymaster/src/V4/PaymasterUtils.test.d.ts +1 -0
  97. package/dist/paymaster/src/V4/PaymasterUtils.test.js +43 -0
  98. package/dist/paymaster/src/V4/SuperPaymasterClient.d.ts +21 -0
  99. package/dist/paymaster/src/V4/SuperPaymasterClient.js +73 -0
  100. package/dist/paymaster/src/V4/SuperPaymasterClient.test.d.ts +1 -0
  101. package/dist/paymaster/src/V4/SuperPaymasterClient.test.js +53 -0
  102. package/dist/paymaster/src/V4/index.d.ts +4 -0
  103. package/dist/paymaster/src/V4/index.js +4 -0
  104. package/dist/paymaster/src/index.d.ts +2 -0
  105. package/dist/paymaster/src/index.js +4 -0
  106. package/package.json +26 -0
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,66 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { PaymasterOperator } from './PaymasterOperator.js';
3
+ describe('PaymasterOperator', () => {
4
+ const MOCK_PM = '0x1111111111111111111111111111111111111111';
5
+ const MOCK_USER = '0x2222222222222222222222222222222222222222';
6
+ const MOCK_TOKEN = '0x3333333333333333333333333333333333333333';
7
+ const MOCK_EP = '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789';
8
+ let mockPublicClient;
9
+ let mockWallet;
10
+ beforeEach(() => {
11
+ vi.clearAllMocks();
12
+ mockPublicClient = {
13
+ readContract: vi.fn(),
14
+ waitForTransactionReceipt: vi.fn().mockResolvedValue({ status: 'success' })
15
+ };
16
+ mockWallet = {
17
+ writeContract: vi.fn().mockResolvedValue('0xhash'),
18
+ account: { address: MOCK_USER },
19
+ chain: { id: 31337 }
20
+ };
21
+ });
22
+ it('should update price', async () => {
23
+ const hash = await PaymasterOperator.updatePrice(mockWallet, MOCK_PM);
24
+ expect(hash).toBe('0xhash');
25
+ });
26
+ it('should get cached price', async () => {
27
+ mockPublicClient.readContract.mockResolvedValue([1000n, 123n]);
28
+ const { price, updatedAt } = await PaymasterOperator.getCachedPrice(mockPublicClient, MOCK_PM);
29
+ expect(price).toBe(1000n);
30
+ expect(updatedAt).toBe(123n);
31
+ });
32
+ it('should check gasless readiness', async () => {
33
+ mockPublicClient.readContract
34
+ .mockResolvedValueOnce([10n ** 18n, true, 10n ** 18n, 100000, 0]) // EntryPoint depositInfo
35
+ .mockResolvedValueOnce([2000n, 123n]) // cachedPrice
36
+ .mockResolvedValueOnce(1n) // tokenPrice
37
+ .mockResolvedValueOnce(1000n) // balance
38
+ .mockResolvedValueOnce(500n); // deposit
39
+ const report = await PaymasterOperator.checkGaslessReadiness(mockPublicClient, MOCK_EP, MOCK_PM, MOCK_USER, MOCK_TOKEN);
40
+ expect(report.isReady).toBe(true);
41
+ expect(report.issues.length).toBe(0);
42
+ });
43
+ it('should identify readiness issues', async () => {
44
+ mockPublicClient.readContract
45
+ .mockResolvedValueOnce([0n, false, 0n, 0, 0]) // EntryPoint depositInfo
46
+ .mockResolvedValueOnce([0n, 0n]) // cachedPrice
47
+ .mockResolvedValueOnce(0n) // tokenPrice
48
+ .mockResolvedValueOnce(0n) // balance
49
+ .mockResolvedValueOnce(0n); // deposit
50
+ const report = await PaymasterOperator.checkGaslessReadiness(mockPublicClient, MOCK_EP, MOCK_PM, MOCK_USER, MOCK_TOKEN);
51
+ expect(report.isReady).toBe(false);
52
+ expect(report.issues.length).toBeGreaterThan(0);
53
+ });
54
+ it('should prepare gasless environment', async () => {
55
+ // Mock readiness check to have issues
56
+ mockPublicClient.readContract
57
+ .mockResolvedValueOnce([0n, false, 0n, 0, 0]) // first check inside prepareGaslessEnvironment
58
+ .mockResolvedValueOnce([0n, 0n])
59
+ .mockResolvedValueOnce(0n)
60
+ .mockResolvedValueOnce(0n)
61
+ .mockResolvedValueOnce(0n);
62
+ const results = await PaymasterOperator.prepareGaslessEnvironment(mockWallet, mockPublicClient, MOCK_EP, MOCK_PM, MOCK_TOKEN);
63
+ expect(results.length).toBeGreaterThan(0);
64
+ expect(mockWallet.writeContract).toHaveBeenCalled();
65
+ });
66
+ });
@@ -0,0 +1,55 @@
1
+ import { type Address, type Hex } from 'viem';
2
+ export type PaymasterV4MiddlewareConfig = {
3
+ paymasterAddress: Address;
4
+ gasToken: Address;
5
+ verificationGasLimit?: bigint;
6
+ postOpGasLimit?: bigint;
7
+ };
8
+ export type GaslessReadinessReport = {
9
+ isReady: boolean;
10
+ issues: string[];
11
+ details: {
12
+ paymasterStake: bigint;
13
+ paymasterDeposit: bigint;
14
+ ethUsdPrice: bigint;
15
+ tokenSupported: boolean;
16
+ tokenPrice: bigint;
17
+ userTokenBalance: bigint;
18
+ userPaymasterDeposit: bigint;
19
+ };
20
+ };
21
+ /**
22
+ * Constructs the middleware for Paymaster V4.
23
+ * Returns the `paymasterAndData` hex string.
24
+ */
25
+ export declare function getPaymasterV4Middleware(config: PaymasterV4MiddlewareConfig): {
26
+ sponsorUserOperation: (args: {
27
+ userOperation: any;
28
+ }) => Promise<{
29
+ paymasterAndData: `0x${string}`;
30
+ verificationGasLimit: bigint;
31
+ preVerificationGas: any;
32
+ }>;
33
+ };
34
+ /**
35
+ * Build paymasterAndData for gasless UserOperation.
36
+ * Layout: [Paymaster(20)] [VerificationGasLimit(16)] [PostOpGasLimit(16)] [Token(20)] [ValidUntil(6)] [ValidAfter(6)]
37
+ */
38
+ export declare function buildPaymasterData(paymasterAddress: Address, token: Address, options?: {
39
+ validityWindow?: number;
40
+ verificationGasLimit?: bigint;
41
+ postOpGasLimit?: bigint;
42
+ }): `0x${string}`;
43
+ /**
44
+ * Build paymasterAndData for SuperPaymaster V3.
45
+ * Layout: [Paymaster(20)] [verGas(16)] [postGas(16)] [operator(20)] [maxRate(32)]
46
+ */
47
+ export declare function buildSuperPaymasterData(paymasterAddress: Address, operator: Address, options?: {
48
+ verificationGasLimit?: bigint;
49
+ postOpGasLimit?: bigint;
50
+ }): `0x${string}`;
51
+ /**
52
+ * Helper to format UserOp for Alchemy/Standard Bundlers (v0.7 Decomposed)
53
+ */
54
+ export declare function formatUserOpV07(userOp: any): any;
55
+ export declare function getUserOpHashV07(userOp: any, entryPoint: Address, chainId: bigint): Hex;
@@ -0,0 +1,124 @@
1
+ import { concat, pad, toHex, keccak256, encodeAbiParameters, toBytes } from 'viem';
2
+ import { validateAddress, validateUint128 } from '@aastar/core';
3
+ const DEFAULT_VERIFICATION_GAS_V4 = 80000n;
4
+ const DEFAULT_POSTOP_GAS_V4 = 100000n;
5
+ /**
6
+ * Constructs the middleware for Paymaster V4.
7
+ * Returns the `paymasterAndData` hex string.
8
+ */
9
+ export function getPaymasterV4Middleware(config) {
10
+ return {
11
+ sponsorUserOperation: async (args) => {
12
+ const verGas = config.verificationGasLimit ?? DEFAULT_VERIFICATION_GAS_V4;
13
+ const postGas = config.postOpGasLimit ?? DEFAULT_POSTOP_GAS_V4;
14
+ // Layout: [Paymaster(20)] [VerGas(16)] [PostOpGas(16)] [Token(20)]
15
+ const paymasterAndData = concat([
16
+ config.paymasterAddress,
17
+ pad(toHex(verGas), { size: 16 }),
18
+ pad(toHex(postGas), { size: 16 }),
19
+ config.gasToken
20
+ ]);
21
+ return {
22
+ paymasterAndData,
23
+ verificationGasLimit: verGas,
24
+ preVerificationGas: args.userOperation.preVerificationGas
25
+ };
26
+ }
27
+ };
28
+ }
29
+ /**
30
+ * Build paymasterAndData for gasless UserOperation.
31
+ * Layout: [Paymaster(20)] [VerificationGasLimit(16)] [PostOpGasLimit(16)] [Token(20)] [ValidUntil(6)] [ValidAfter(6)]
32
+ */
33
+ export function buildPaymasterData(paymasterAddress, token, options) {
34
+ const validityWindow = options?.validityWindow ?? 3600;
35
+ const verGas = options?.verificationGasLimit ?? 80000n;
36
+ const postGas = options?.postOpGasLimit ?? 100000n;
37
+ // Hardening: uint128 bounds check
38
+ validateUint128(verGas, 'verificationGasLimit');
39
+ validateUint128(postGas, 'postOpGasLimit');
40
+ const now = Math.floor(Date.now() / 1000);
41
+ const validUntil = now + validityWindow;
42
+ const validAfter = now - 100; // 100 seconds grace period
43
+ return concat([
44
+ paymasterAddress,
45
+ pad(toHex(verGas), { size: 16 }),
46
+ pad(toHex(postGas), { size: 16 }),
47
+ token,
48
+ pad(toHex(validUntil), { size: 6 }),
49
+ pad(toHex(validAfter), { size: 6 })
50
+ ]);
51
+ }
52
+ /**
53
+ * Build paymasterAndData for SuperPaymaster V3.
54
+ * Layout: [Paymaster(20)] [verGas(16)] [postGas(16)] [operator(20)] [maxRate(32)]
55
+ */
56
+ export function buildSuperPaymasterData(paymasterAddress, operator, options) {
57
+ const verGas = options?.verificationGasLimit ?? 80000n;
58
+ const postGas = options?.postOpGasLimit ?? 100000n;
59
+ // Hardening
60
+ validateAddress(paymasterAddress, 'Paymaster Address');
61
+ validateAddress(operator, 'Operator Address');
62
+ validateUint128(verGas, 'verificationGasLimit');
63
+ validateUint128(postGas, 'postOpGasLimit');
64
+ return concat([
65
+ paymasterAddress,
66
+ pad(toHex(verGas), { size: 16 }),
67
+ pad(toHex(postGas), { size: 16 }),
68
+ operator
69
+ ]);
70
+ }
71
+ /**
72
+ * Helper to format UserOp for Alchemy/Standard Bundlers (v0.7 Decomposed)
73
+ */
74
+ export function formatUserOpV07(userOp) {
75
+ const result = {
76
+ sender: userOp.sender,
77
+ nonce: toHex(userOp.nonce),
78
+ callData: userOp.callData,
79
+ preVerificationGas: toHex(userOp.preVerificationGas),
80
+ signature: userOp.signature,
81
+ initCode: userOp.initCode
82
+ };
83
+ // Extract Factory/FactoryData if present
84
+ if (userOp.initCode && userOp.initCode !== '0x') {
85
+ result.factory = userOp.initCode.slice(0, 42);
86
+ result.factoryData = '0x' + userOp.initCode.slice(42);
87
+ }
88
+ // Unpack accountGasLimits: [verificationGasLimit(16)][callGasLimit(16)]
89
+ if (userOp.accountGasLimits && userOp.accountGasLimits !== '0x') {
90
+ const packed = userOp.accountGasLimits.replace('0x', '').padStart(64, '0');
91
+ result.verificationGasLimit = '0x' + BigInt('0x' + packed.slice(0, 32)).toString(16);
92
+ result.callGasLimit = '0x' + BigInt('0x' + packed.slice(32, 64)).toString(16);
93
+ }
94
+ // Unpack gasFees: [maxPriorityFee(16)][maxFee(16)]
95
+ if (userOp.gasFees && userOp.gasFees !== '0x') {
96
+ const packed = userOp.gasFees.replace('0x', '').padStart(64, '0');
97
+ result.maxPriorityFeePerGas = '0x' + BigInt('0x' + packed.slice(0, 32)).toString(16);
98
+ result.maxFeePerGas = '0x' + BigInt('0x' + packed.slice(32, 64)).toString(16);
99
+ }
100
+ // Unpack paymasterAndData: [paymaster(20)][verificationGas(16)][postOpGas(16)][paymasterData]
101
+ if (userOp.paymasterAndData && userOp.paymasterAndData !== '0x') {
102
+ const packed = userOp.paymasterAndData.replace('0x', '');
103
+ if (packed.length >= 104) {
104
+ result.paymaster = '0x' + packed.slice(0, 40);
105
+ result.paymasterVerificationGasLimit = '0x' + BigInt('0x' + packed.slice(40, 72)).toString(16);
106
+ result.paymasterPostOpGasLimit = '0x' + BigInt('0x' + packed.slice(72, 104)).toString(16);
107
+ result.paymasterData = '0x' + packed.slice(104);
108
+ }
109
+ }
110
+ return result;
111
+ }
112
+ export function getUserOpHashV07(userOp, entryPoint, chainId) {
113
+ const hashedUserOp = keccak256(encodeAbiParameters(['address', 'uint256', 'bytes32', 'bytes32', 'bytes32', 'uint256', 'bytes32', 'bytes32'].map(t => ({ type: t })), [
114
+ userOp.sender,
115
+ userOp.nonce,
116
+ keccak256(toBytes(userOp.initCode)),
117
+ keccak256(toBytes(userOp.callData)),
118
+ userOp.accountGasLimits,
119
+ toHex(userOp.preVerificationGas),
120
+ userOp.gasFees,
121
+ keccak256(toBytes(userOp.paymasterAndData))
122
+ ]));
123
+ return keccak256(encodeAbiParameters(['bytes32', 'address', 'uint256'].map(t => ({ type: t })), [hashedUserOp, entryPoint, chainId]));
124
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,43 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { getPaymasterV4Middleware, buildPaymasterData, buildSuperPaymasterData, formatUserOpV07 } from './PaymasterUtils.js';
3
+ describe('PaymasterUtils', () => {
4
+ const MOCK_PM = '0x1111111111111111111111111111111111111111';
5
+ const MOCK_TOKEN = '0x2222222222222222222222222222222222222222';
6
+ const MOCK_OPERATOR = '0x3333333333333333333333333333333333333333';
7
+ it('should get V4 middleware', async () => {
8
+ const middleware = getPaymasterV4Middleware({
9
+ paymasterAddress: MOCK_PM,
10
+ gasToken: MOCK_TOKEN
11
+ });
12
+ const result = await middleware.sponsorUserOperation({
13
+ userOperation: { preVerificationGas: 100n }
14
+ });
15
+ expect(result.paymasterAndData).toBeDefined();
16
+ expect(result.paymasterAndData.toLowerCase()).toContain(MOCK_PM.toLowerCase().replace('0x', ''));
17
+ });
18
+ it('should build paymaster data for V4', () => {
19
+ const data = buildPaymasterData(MOCK_PM, MOCK_TOKEN);
20
+ expect(data.length).toBe(2 + 40 + 32 + 32 + 40 + 12 + 12); // Layout check
21
+ });
22
+ it('should build super paymaster data', () => {
23
+ const data = buildSuperPaymasterData(MOCK_PM, MOCK_OPERATOR);
24
+ expect(data.toLowerCase()).toContain(MOCK_OPERATOR.toLowerCase().replace('0x', ''));
25
+ });
26
+ it('should format UserOp for v0.7', () => {
27
+ const userOp = {
28
+ sender: MOCK_PM,
29
+ nonce: 1n,
30
+ callData: '0x123',
31
+ preVerificationGas: 1000n,
32
+ accountGasLimits: '0x' + '1'.repeat(32) + '2'.repeat(32),
33
+ gasFees: '0x' + '3'.repeat(32) + '4'.repeat(32),
34
+ paymasterAndData: '0x' + MOCK_PM.slice(2) + '5'.repeat(32) + '6'.repeat(32) + '7788',
35
+ signature: '0x'
36
+ };
37
+ const formatted = formatUserOpV07(userOp);
38
+ expect(formatted.sender).toBe(MOCK_PM);
39
+ expect(formatted.verificationGasLimit).toBeDefined();
40
+ expect(formatted.maxFeePerGas).toBeDefined();
41
+ expect(formatted.paymaster).toBe(MOCK_PM);
42
+ });
43
+ });
@@ -0,0 +1,21 @@
1
+ import { type Address, type Hex } from 'viem';
2
+ export type GaslessTransactionConfig = {
3
+ token: Address;
4
+ recipient: Address;
5
+ amount: bigint;
6
+ operator: Address;
7
+ paymasterAddress: Address;
8
+ factory?: Address;
9
+ factoryData?: Hex;
10
+ };
11
+ /**
12
+ * SuperPaymasterClient
13
+ * High-level API for SuperPaymaster operations, including dynamic gas estimation.
14
+ */
15
+ export declare class SuperPaymasterClient {
16
+ /**
17
+ * Submit a gasless transaction using SuperPaymaster.
18
+ * Automatically handles gas estimation with a smart efficiency buffer.
19
+ */
20
+ static submitGaslessTransaction(client: any, wallet: any, aaAddress: Address, entryPoint: Address, bundlerUrl: string, config: GaslessTransactionConfig): Promise<Hex>;
21
+ }
@@ -0,0 +1,73 @@
1
+ import { encodeFunctionData, parseAbi } from 'viem';
2
+ import { PaymasterClient } from './PaymasterClient';
3
+ import { validateAddress, validateAmount } from '@aastar/core';
4
+ /**
5
+ * SuperPaymasterClient
6
+ * High-level API for SuperPaymaster operations, including dynamic gas estimation.
7
+ */
8
+ export class SuperPaymasterClient {
9
+ /**
10
+ * Submit a gasless transaction using SuperPaymaster.
11
+ * Automatically handles gas estimation with a smart efficiency buffer.
12
+ */
13
+ static async submitGaslessTransaction(client, wallet, aaAddress, entryPoint, bundlerUrl, config) {
14
+ // Validation (Phase 0 Hardening)
15
+ validateAddress(config.token, 'Token Address');
16
+ validateAddress(config.recipient, 'Recipient Address');
17
+ validateAddress(config.operator, 'Operator Address');
18
+ validateAddress(config.paymasterAddress, 'Paymaster Address');
19
+ validateAmount(config.amount, 'Amount', 1n); // Must be > 0
20
+ // 1. Prepare Calldata (Standard ERC20 Transfer)
21
+ const callData = encodeFunctionData({
22
+ abi: parseAbi(['function execute(address dest, uint256 value, bytes func) external']),
23
+ functionName: 'execute',
24
+ args: [
25
+ config.token,
26
+ 0n,
27
+ encodeFunctionData({
28
+ abi: parseAbi(['function transfer(address to, uint256 amount) external returns (bool)']),
29
+ functionName: 'transfer',
30
+ args: [config.recipient, config.amount]
31
+ })
32
+ ]
33
+ });
34
+ // 2. Initial Gas Estimation (Bundler Query)
35
+ console.log('[SuperPaymasterClient] ☁️ Estimating Gas usage...');
36
+ const est = await PaymasterClient.estimateUserOperationGas(client, wallet, aaAddress, entryPoint, config.paymasterAddress, config.token, bundlerUrl, callData, {
37
+ operator: config.operator,
38
+ factory: config.factory,
39
+ factoryData: config.factoryData
40
+ });
41
+ console.log('[SuperPaymasterClient] ☁️ Bundler Estimates:', est);
42
+ // 3. Apply Smart Buffer Strategy
43
+ // We need to ensure:
44
+ // A. verificationGasLimit >= est.verificationGasLimit (Bundler's minimum)
45
+ // B. verificationGasLimit >= SuperPaymaster's Actual Usage (~80k-100k)
46
+ // C. verificationGasLimit / PreVerificationGas > 0.4 (Efficiency Ratio) PRE-CHECK
47
+ // Actually, the Bundler checks: (gas limits) / (actual gas used) > efficiency.
48
+ // So we must NOT set limits WAY higher than actual usage.
49
+ // Best strategy: Use Bundler's Estimate + Small Buffer (e.g. 10-20k).
50
+ // SuperPaymaster Logic Cost: ~80,000 to 120,000 gas depending on cold storage
51
+ // Bundler Estimate usually returns the *actual execution path* gas.
52
+ let vgl = est.verificationGasLimit;
53
+ // Safety Floor: If estimate is suspiciously low (e.g. < 50k), bump it for PM logic
54
+ // But if we bump it too high, we hit "Efficiency too low".
55
+ // Let's trust the bundler's estimate but add a fixed safety pad for dynamic storage
56
+ const SAFETY_PAD = 20000n;
57
+ const tunedVGL = vgl + SAFETY_PAD;
58
+ // Same for PostOp
59
+ const tunedPostOp = est.paymasterPostOpGasLimit + 10000n;
60
+ console.log(`[SuperPaymasterClient] 🔧 Tuned Limits: VGL=${tunedVGL}, PostOp=${tunedPostOp}`);
61
+ // 4. Submit with Tuned Limits
62
+ return PaymasterClient.submitGaslessUserOperation(client, wallet, aaAddress, entryPoint, config.paymasterAddress, config.token, bundlerUrl, callData, {
63
+ operator: config.operator,
64
+ verificationGasLimit: tunedVGL,
65
+ callGasLimit: est.callGasLimit,
66
+ preVerificationGas: est.preVerificationGas,
67
+ paymasterPostOpGasLimit: tunedPostOp, // Pass specific PM limits if supported
68
+ autoEstimate: false, // We did it ourselves
69
+ factory: config.factory,
70
+ factoryData: config.factoryData
71
+ });
72
+ }
73
+ }
@@ -0,0 +1,53 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { SuperPaymasterClient } from './SuperPaymasterClient.js';
3
+ import { PaymasterClient } from './PaymasterClient.js';
4
+ // Mock PaymasterClient
5
+ vi.mock('./PaymasterClient.js', () => ({
6
+ PaymasterClient: {
7
+ estimateUserOperationGas: vi.fn(),
8
+ submitGaslessUserOperation: vi.fn()
9
+ }
10
+ }));
11
+ describe('SuperPaymasterClient', () => {
12
+ const MOCK_PM = '0x1111111111111111111111111111111111111111';
13
+ const MOCK_USER = '0x2222222222222222222222222222222222222222';
14
+ const MOCK_TOKEN = '0x3333333333333333333333333333333333333333';
15
+ const MOCK_RECIPIENT = '0x4444444444444444444444444444444444444444';
16
+ const MOCK_OPERATOR = '0x5555555555555555555555555555555555555555';
17
+ const MOCK_EP = '0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789';
18
+ beforeEach(() => {
19
+ vi.clearAllMocks();
20
+ });
21
+ it('should submit gasless transaction with tuned limits', async () => {
22
+ PaymasterClient.estimateUserOperationGas.mockResolvedValue({
23
+ verificationGasLimit: 100000n,
24
+ callGasLimit: 200000n,
25
+ preVerificationGas: 50000n,
26
+ paymasterPostOpGasLimit: 100000n
27
+ });
28
+ PaymasterClient.submitGaslessUserOperation.mockResolvedValue('0xuserOpHash');
29
+ const hash = await SuperPaymasterClient.submitGaslessTransaction({}, // client
30
+ {}, // wallet
31
+ MOCK_USER, MOCK_EP, 'http://bundler', {
32
+ token: MOCK_TOKEN,
33
+ recipient: MOCK_RECIPIENT,
34
+ amount: 100n,
35
+ operator: MOCK_OPERATOR,
36
+ paymasterAddress: MOCK_PM
37
+ });
38
+ expect(hash).toBe('0xuserOpHash');
39
+ expect(PaymasterClient.submitGaslessUserOperation).toHaveBeenCalledWith(expect.anything(), expect.anything(), expect.anything(), expect.anything(), expect.anything(), expect.anything(), expect.anything(), expect.anything(), expect.objectContaining({
40
+ verificationGasLimit: 120000n, // 100k + 20k buffer
41
+ autoEstimate: false
42
+ }));
43
+ });
44
+ it('should throw on invalid configuration', async () => {
45
+ await expect(SuperPaymasterClient.submitGaslessTransaction({}, {}, MOCK_USER, MOCK_EP, 'http://bundler', {
46
+ token: 'invalid',
47
+ recipient: MOCK_RECIPIENT,
48
+ amount: 100n,
49
+ operator: MOCK_OPERATOR,
50
+ paymasterAddress: MOCK_PM
51
+ })).rejects.toThrow();
52
+ });
53
+ });
@@ -0,0 +1,4 @@
1
+ export * from './PaymasterUtils';
2
+ export * from './PaymasterClient';
3
+ export * from './PaymasterOperator';
4
+ export * from './SuperPaymasterClient';
@@ -0,0 +1,4 @@
1
+ export * from './PaymasterUtils';
2
+ export * from './PaymasterClient';
3
+ export * from './PaymasterOperator';
4
+ export * from './SuperPaymasterClient';
@@ -0,0 +1,2 @@
1
+ export * from './SuperPaymaster/index.js';
2
+ export * from './V4/index.js';
@@ -0,0 +1,4 @@
1
+ // SuperPaymaster middleware
2
+ export * from './SuperPaymaster/index.js';
3
+ // Paymaster V4 middleware
4
+ export * from './V4/index.js';
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@aastar/paymaster",
3
+ "version": "0.16.7",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "dependencies": {
11
+ "viem": "2.43.3",
12
+ "@aastar/core": "0.16.7"
13
+ },
14
+ "devDependencies": {
15
+ "typescript": "5.7.2"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "license": "MIT",
21
+ "scripts": {
22
+ "clean": "find src -name '*.js' -o -name '*.d.ts' -o -name '*.map' | xargs rm -f",
23
+ "prebuild": "pnpm clean",
24
+ "build": "tsc"
25
+ }
26
+ }