@aastar/enduser 0.16.12 → 0.16.16

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,141 @@
1
+ import { concat, pad, toHex, keccak256, encodeAbiParameters, toBytes } from 'viem';
2
+ const DEFAULT_VERIFICATION_GAS_V4 = 1500000n; // ~1.5M for safety
3
+ const DEFAULT_POSTOP_GAS_V4 = 300000n; // ~300k for postOp logic
4
+ /**
5
+ * Constructs the middleware for Paymaster V4.
6
+ * Returns the `paymasterAndData` hex string.
7
+ */
8
+ export function getPaymasterV4Middleware(config) {
9
+ return {
10
+ sponsorUserOperation: async (args) => {
11
+ const verGas = config.verificationGasLimit ?? DEFAULT_VERIFICATION_GAS_V4;
12
+ const postGas = config.postOpGasLimit ?? DEFAULT_POSTOP_GAS_V4;
13
+ // Layout: [Paymaster(20)] [VerGas(16)] [PostOpGas(16)] [Token(20)]
14
+ const paymasterAndData = concat([
15
+ config.paymasterAddress,
16
+ pad(toHex(verGas), { size: 16 }),
17
+ pad(toHex(postGas), { size: 16 }),
18
+ config.gasToken
19
+ ]);
20
+ return {
21
+ paymasterAndData,
22
+ verificationGasLimit: verGas,
23
+ preVerificationGas: args.userOperation.preVerificationGas
24
+ };
25
+ }
26
+ };
27
+ }
28
+ /**
29
+ * Build paymasterAndData for gasless UserOperation.
30
+ * Layout: [Paymaster(20)] [VerificationGasLimit(16)] [PostOpGasLimit(16)] [Token(20)] [ValidUntil(6)] [ValidAfter(6)]
31
+ */
32
+ export function buildPaymasterData(paymasterAddress, token, options) {
33
+ const validityWindow = options?.validityWindow ?? 3600;
34
+ const verGas = options?.verificationGasLimit ?? 200000n; // Increased for estimation
35
+ const postGas = options?.postOpGasLimit ?? 100000n;
36
+ const now = Math.floor(Date.now() / 1000);
37
+ const validUntil = now + validityWindow;
38
+ const validAfter = now - 100; // 100 seconds grace period
39
+ return concat([
40
+ paymasterAddress,
41
+ pad(toHex(verGas), { size: 16 }),
42
+ pad(toHex(postGas), { size: 16 }),
43
+ token,
44
+ pad(toHex(validUntil), { size: 6 }),
45
+ pad(toHex(validAfter), { size: 6 })
46
+ ]);
47
+ }
48
+ /**
49
+ * Build paymasterAndData for SuperPaymaster V3.
50
+ * Layout: [Paymaster(20)] [verGas(16)] [postGas(16)] [operator(20)] [maxRate(32)]
51
+ * Total: 104 bytes
52
+ *
53
+ * IMPORTANT: SuperPaymaster contract generates validUntil internally using:
54
+ * validUntil = cachedPrice.updatedAt + priceStalenessThreshold
55
+ * Do NOT include validUntil/validAfter in paymasterAndData!
56
+ */
57
+ export function buildSuperPaymasterData(paymasterAddress, operator, options) {
58
+ const verGas = options?.verificationGasLimit ?? 80000n;
59
+ const postGas = options?.postOpGasLimit ?? 100000n;
60
+ const maxRate = options?.maxRate ?? ((1n << 256n) - 1n); // Default: max uint256, no rate limit
61
+ return concat([
62
+ paymasterAddress,
63
+ pad(toHex(verGas), { size: 16 }),
64
+ pad(toHex(postGas), { size: 16 }),
65
+ operator,
66
+ pad(toHex(maxRate), { size: 32 }) // Optional rate commitment (rug pull protection)
67
+ ]);
68
+ }
69
+ /**
70
+ * Helper to format UserOp for Alchemy/Standard Bundlers (v0.7 Decomposed)
71
+ */
72
+ export function formatUserOpV07(userOp) {
73
+ const result = {
74
+ sender: userOp.sender,
75
+ nonce: toHex(userOp.nonce),
76
+ callData: userOp.callData,
77
+ preVerificationGas: toHex(userOp.preVerificationGas),
78
+ signature: userOp.signature
79
+ };
80
+ // Only include factory/factoryData if account is NOT deployed (initCode not empty)
81
+ if (userOp.initCode && userOp.initCode !== '0x' && userOp.initCode.length > 2) {
82
+ result.initCode = userOp.initCode;
83
+ if (userOp.initCode.length > 42) {
84
+ result.factory = userOp.initCode.slice(0, 42);
85
+ result.factoryData = '0x' + userOp.initCode.slice(42);
86
+ }
87
+ else {
88
+ result.factory = '0x0000000000000000000000000000000000000000';
89
+ result.factoryData = '0x';
90
+ }
91
+ }
92
+ // If account is deployed, don't include any factory fields at all
93
+ // Unpack accountGasLimits: [verificationGasLimit(16)][callGasLimit(16)]
94
+ if (userOp.accountGasLimits && userOp.accountGasLimits !== '0x') {
95
+ const packed = userOp.accountGasLimits.replace('0x', '').padStart(64, '0');
96
+ result.verificationGasLimit = '0x' + BigInt('0x' + packed.slice(0, 32)).toString(16);
97
+ result.callGasLimit = '0x' + BigInt('0x' + packed.slice(32, 64)).toString(16);
98
+ }
99
+ // Unpack gasFees: [maxPriorityFee(16)][maxFee(16)]
100
+ if (userOp.gasFees && userOp.gasFees !== '0x') {
101
+ const packed = userOp.gasFees.replace('0x', '').padStart(64, '0');
102
+ result.maxPriorityFeePerGas = '0x' + BigInt('0x' + packed.slice(0, 32)).toString(16);
103
+ result.maxFeePerGas = '0x' + BigInt('0x' + packed.slice(32, 64)).toString(16);
104
+ }
105
+ // Unpack paymasterAndData: [paymaster(20)][verificationGas(16)][postOpGas(16)][paymasterData]
106
+ if (userOp.paymasterAndData && userOp.paymasterAndData !== '0x') {
107
+ const packed = userOp.paymasterAndData.replace('0x', '');
108
+ if (packed.length >= 104) {
109
+ result.paymaster = '0x' + packed.slice(0, 40);
110
+ result.paymasterVerificationGasLimit = '0x' + BigInt('0x' + packed.slice(40, 72)).toString(16);
111
+ result.paymasterPostOpGasLimit = '0x' + BigInt('0x' + packed.slice(72, 104)).toString(16);
112
+ result.paymasterData = '0x' + packed.slice(104);
113
+ }
114
+ }
115
+ return result;
116
+ }
117
+ export function getUserOpHashV07(userOp, entryPoint, chainId) {
118
+ const hashedUserOp = keccak256(encodeAbiParameters(['address', 'uint256', 'bytes32', 'bytes32', 'bytes32', 'uint256', 'bytes32', 'bytes32'].map(t => ({ type: t })), [
119
+ userOp.sender,
120
+ userOp.nonce,
121
+ keccak256(toBytes(userOp.initCode)),
122
+ keccak256(toBytes(userOp.callData)),
123
+ userOp.accountGasLimits,
124
+ toHex(userOp.preVerificationGas),
125
+ userOp.gasFees,
126
+ keccak256(toBytes(userOp.paymasterAndData))
127
+ ]));
128
+ return keccak256(encodeAbiParameters(['bytes32', 'address', 'uint256'].map(t => ({ type: t })), [hashedUserOp, entryPoint, chainId]));
129
+ }
130
+ /**
131
+ * Tune gas limit using a dynamic nominal ceiling to satisfy Bundler efficiency (0.4)
132
+ * Target: Actual / Limit >= targetEfficiency
133
+ */
134
+ export function tuneGasLimit(estimate, nominalActual, targetEfficiency = 0.45) {
135
+ if (estimate === 0n)
136
+ return 0n;
137
+ // targetEfficiency = actual / ceiling => ceiling = actual / targetEfficiency
138
+ const ceiling = (nominalActual * 100n) / BigInt(Math.floor(targetEfficiency * 100));
139
+ // Return the more restrictive limit to ensure efficiency ratio is met
140
+ return estimate < ceiling ? estimate : ceiling;
141
+ }
@@ -1,4 +1,5 @@
1
- import { Address, Hash, PublicClient, WalletClient } from 'viem';
1
+ import { Address, Hash } from 'viem';
2
+ import { type PublicClient, type WalletClient } from '@aastar/core';
2
3
  /**
3
4
  * PhD Paper Experiment Test Toolkit
4
5
  *
@@ -29,9 +30,15 @@ import { Address, Hash, PublicClient, WalletClient } from 'viem';
29
30
  * ```
30
31
  */
31
32
  export declare class TestAccountManager {
33
+ /** @internal */
32
34
  private publicClient;
35
+ /** @internal */
33
36
  private walletClient;
34
- constructor(publicClient: PublicClient, walletClient: WalletClient);
37
+ constructor(
38
+ /** @internal */
39
+ publicClient: PublicClient,
40
+ /** @internal */
41
+ walletClient: WalletClient);
35
42
  /**
36
43
  * Prepare complete test environment for PhD experiments
37
44
  *
@@ -33,7 +33,11 @@ import { accountFactoryActions, TEST_ACCOUNT_ADDRESSES } from '@aastar/core';
33
33
  export class TestAccountManager {
34
34
  publicClient;
35
35
  walletClient;
36
- constructor(publicClient, walletClient) {
36
+ constructor(
37
+ /** @internal */
38
+ publicClient,
39
+ /** @internal */
40
+ walletClient) {
37
41
  this.publicClient = publicClient;
38
42
  this.walletClient = walletClient;
39
43
  if (!walletClient.account) {
package/package.json CHANGED
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "name": "@aastar/enduser",
3
- "version": "0.16.12",
3
+ "version": "0.16.16",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
4
7
  "type": "module",
5
8
  "description": "Enduser client for AAstar SDK",
6
9
  "main": "dist/index.js",
@@ -17,10 +20,11 @@
17
20
  "license": "MIT",
18
21
  "dependencies": {
19
22
  "viem": "2.43.3",
20
- "@aastar/core": "0.16.12"
23
+ "@aastar/core": "0.16.16"
21
24
  },
22
25
  "devDependencies": {
23
- "typescript": "5.7.2"
26
+ "typescript": "5.7.2",
27
+ "vitest": "4.0.17"
24
28
  },
25
29
  "scripts": {
26
30
  "build": "tsc",