gokite-aa-sdk 1.0.0

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/utils.js ADDED
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createUserOpForEstimation = exports.generateDummySignature = exports.generateSalt = exports.serializeUserOperation = exports.getUserOperationHash = exports.packPaymasterAndData = exports.packAccountGasLimits = exports.packUserOperation = exports.encodeFunctionCall = exports.getAccountAddress = void 0;
4
+ const ethers_1 = require("ethers");
5
+ /**
6
+ * Calculate the counterfactual address of a GokiteAccount
7
+ * This matches the logic in GokiteAccountFactory.getAddress()
8
+ */
9
+ function getAccountAddress(factoryAddress, implementationAddress, owner, salt) {
10
+ const proxyCreationCode = '0x60806040526102c68038038061001481610188565b928339810190604081830312610183578051906001600160a01b03821690818303610183576020810151906001600160401b038211610183570183601f820112156101835780519061006d610068836101c3565b610188565b94828652602083830101116101835760005b82811061016e575050602060009185010152813b1561015a577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a28151156101415760008083602061012995519101845af43d15610139573d91610119610068846101c3565b9283523d6000602085013e6101de565b505b604051608690816102408239f35b6060916101de565b5050341561012b5763b398979f60e01b60005260046000fd5b634c9c8ce360e01b60005260045260246000fd5b8060208092840101518282890101520161007f565b600080fd5b6040519190601f01601f191682016001600160401b038111838210176101ad57604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b0381116101ad57601f01601f191660200190565b9061020457508051156101f357805190602001fd5b630a12f52160e11b60005260046000fd5b81511580610236575b610215575090565b639996b31560e01b60009081526001600160a01b0391909116600452602490fd5b50803b1561020d56fe60806040527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5460009081906001600160a01b0316368280378136915af43d6000803e15604b573d6000f35b3d6000fdfea26469706673582212201d39938ba86a38b154a247ca9c527d397a6a764ffd2fae8535a9595bf97d45a764736f6c634300081c0033';
11
+ const initializeCallData = encodeFunctionCall(['function initialize(address)'], 'initialize', [owner]);
12
+ const constructorArgs = ethers_1.ethers.AbiCoder.defaultAbiCoder().encode(['address', 'bytes'], [implementationAddress, initializeCallData]);
13
+ // Full creation code = creation code + constructor args
14
+ const fullCreationCode = proxyCreationCode + constructorArgs.slice(2);
15
+ return ethers_1.ethers.getCreate2Address(factoryAddress, ethers_1.ethers.zeroPadValue(ethers_1.ethers.toBeHex(salt), 32), ethers_1.ethers.keccak256(fullCreationCode));
16
+ }
17
+ exports.getAccountAddress = getAccountAddress;
18
+ /**
19
+ * Encode function call data
20
+ */
21
+ function encodeFunctionCall(abi, functionName, params) {
22
+ const iface = new ethers_1.ethers.Interface(abi);
23
+ return iface.encodeFunctionData(functionName, params);
24
+ }
25
+ exports.encodeFunctionCall = encodeFunctionCall;
26
+ /**
27
+ * Pack user operation for hashing
28
+ */
29
+ function packUserOperation(userOp) {
30
+ const packed = ethers_1.ethers.AbiCoder.defaultAbiCoder().encode([
31
+ 'address', 'uint256', 'bytes', 'bytes',
32
+ 'uint256', 'uint256', 'uint256', 'uint256', 'uint256',
33
+ 'bytes'
34
+ ], [
35
+ userOp.sender,
36
+ userOp.nonce,
37
+ ethers_1.ethers.keccak256(userOp.initCode),
38
+ ethers_1.ethers.keccak256(userOp.callData),
39
+ userOp.callGasLimit,
40
+ userOp.verificationGasLimit,
41
+ userOp.preVerificationGas,
42
+ userOp.maxFeePerGas,
43
+ userOp.maxPriorityFeePerGas,
44
+ ethers_1.ethers.keccak256(userOp.paymasterAndData)
45
+ ]);
46
+ return packed;
47
+ }
48
+ exports.packUserOperation = packUserOperation;
49
+ /**
50
+ * Pack account gas limits into 32 bytes
51
+ * @param verificationGasLimit Verification gas limit (16 bytes, first half)
52
+ * @param callGasLimit Call gas limit (16 bytes, second half)
53
+ * @returns 32 bytes packed data as hex string
54
+ */
55
+ function packAccountGasLimits(verificationGasLimit, callGasLimit) {
56
+ // Ensure values don't exceed uint128 (2^128 - 1)
57
+ const uint128Max = (BigInt(1) << BigInt(128)) - BigInt(1);
58
+ if (verificationGasLimit > uint128Max || callGasLimit > uint128Max) {
59
+ throw new Error('Gas limit exceeds uint128 maximum');
60
+ }
61
+ // Pack verificationGasLimit into first 16 bytes, callGasLimit into last 16 bytes
62
+ const verificationHex = verificationGasLimit.toString(16).padStart(32, '0'); // 16 bytes = 32 hex chars
63
+ const callGasHex = callGasLimit.toString(16).padStart(32, '0'); // 16 bytes = 32 hex chars
64
+ return '0x' + verificationHex + callGasHex;
65
+ }
66
+ exports.packAccountGasLimits = packAccountGasLimits;
67
+ /**
68
+ * Pack paymaster and data
69
+ * @param paymasterAddress Paymaster contract address (20 bytes)
70
+ * @param paymasterVerificationGasLimit Paymaster verification gas limit (16 bytes)
71
+ * @param postOpGasLimit Post operation gas limit (16 bytes)
72
+ * @param paymasterData Additional paymaster data (variable length)
73
+ * @returns Packed paymaster and data as hex string
74
+ */
75
+ function packPaymasterAndData(paymasterAddress, paymasterVerificationGasLimit, postOpGasLimit, paymasterData = '0x') {
76
+ if (paymasterAddress === '0x' || paymasterAddress === '0x0000000000000000000000000000000000000000') {
77
+ return '0x';
78
+ }
79
+ // Ensure values don't exceed uint128 (2^128 - 1)
80
+ const uint128Max = (BigInt(1) << BigInt(128)) - BigInt(1);
81
+ if (paymasterVerificationGasLimit > uint128Max || postOpGasLimit > uint128Max) {
82
+ throw new Error('Gas limit exceeds uint128 maximum');
83
+ }
84
+ // Remove 0x prefix if present
85
+ const cleanAddress = paymasterAddress.startsWith('0x') ? paymasterAddress.slice(2) : paymasterAddress;
86
+ const cleanData = paymasterData.startsWith('0x') ? paymasterData.slice(2) : paymasterData;
87
+ // Pack: address (20 bytes) + paymasterVerificationGasLimit (16 bytes) + postOpGasLimit (16 bytes) + paymasterData
88
+ const paymasterVerificationHex = paymasterVerificationGasLimit.toString(16).padStart(32, '0'); // 16 bytes
89
+ const postOpHex = postOpGasLimit.toString(16).padStart(32, '0'); // 16 bytes
90
+ return '0x' + cleanAddress + paymasterVerificationHex + postOpHex + cleanData;
91
+ }
92
+ exports.packPaymasterAndData = packPaymasterAndData;
93
+ /**
94
+ * Get user operation hash
95
+ */
96
+ function getUserOperationHash(userOp, entryPointAddress, chainId) {
97
+ const packed = packUserOperation(userOp);
98
+ const enc = ethers_1.ethers.AbiCoder.defaultAbiCoder().encode(['bytes32', 'address', 'uint256'], [ethers_1.ethers.keccak256(packed), entryPointAddress, chainId]);
99
+ return ethers_1.ethers.keccak256(enc);
100
+ }
101
+ exports.getUserOperationHash = getUserOperationHash;
102
+ /**
103
+ * Convert bigint values to hex strings for JSON serialization
104
+ * Also unpacks PackedUserOperation format to legacy format for bundler compatibility
105
+ */
106
+ function serializeUserOperation(userOp) {
107
+ // Unpack accountGasLimits (32 bytes): verificationGasLimit (16 bytes) + callGasLimit (16 bytes)
108
+ const accountGasLimitsHex = userOp.accountGasLimits.startsWith('0x') ? userOp.accountGasLimits.slice(2) : userOp.accountGasLimits;
109
+ const verificationGasLimitHex = accountGasLimitsHex.slice(0, 32); // First 16 bytes (32 hex chars)
110
+ const callGasLimitHex = accountGasLimitsHex.slice(32, 64); // Last 16 bytes (32 hex chars)
111
+ // Unpack gasFees (32 bytes): maxPriorityFeePerGas (16 bytes) + maxFeePerGas (16 bytes)
112
+ const gasFeesHex = userOp.gasFees.startsWith('0x') ? userOp.gasFees.slice(2) : userOp.gasFees;
113
+ const maxPriorityFeePerGasHex = gasFeesHex.slice(0, 32); // First 16 bytes (32 hex chars)
114
+ const maxFeePerGasHex = gasFeesHex.slice(32, 64); // Last 16 bytes (32 hex chars)
115
+ return {
116
+ sender: userOp.sender,
117
+ nonce: ethers_1.ethers.toBeHex(userOp.nonce),
118
+ initCode: userOp.initCode,
119
+ callData: userOp.callData,
120
+ // Unpack to legacy format for bundler compatibility
121
+ callGasLimit: '0x' + callGasLimitHex,
122
+ verificationGasLimit: '0x' + verificationGasLimitHex,
123
+ preVerificationGas: ethers_1.ethers.toBeHex(userOp.preVerificationGas),
124
+ maxFeePerGas: '0x' + maxFeePerGasHex,
125
+ maxPriorityFeePerGas: '0x' + maxPriorityFeePerGasHex,
126
+ paymasterAndData: userOp.paymasterAndData,
127
+ signature: userOp.signature
128
+ };
129
+ }
130
+ exports.serializeUserOperation = serializeUserOperation;
131
+ // default salt is 0
132
+ function generateSalt() {
133
+ return BigInt(0);
134
+ }
135
+ exports.generateSalt = generateSalt;
136
+ /**
137
+ * Generate a dummy signature for gas estimation
138
+ * The signature needs to be the correct length but doesn't need to be valid
139
+ * Using a format that won't cause ECDSA.recover to revert
140
+ */
141
+ function generateDummySignature() {
142
+ return "0x59c044382c5418739ef913865b05f60050f8e587041548215aa595816dfbe77b26408ebd368bc51be61008aaef7b9b87479c91f9c297caf1e33e8c3b2de69a3b1c";
143
+ }
144
+ exports.generateDummySignature = generateDummySignature;
145
+ /**
146
+ * Create a user operation with dummy signature for gas estimation
147
+ */
148
+ function createUserOpForEstimation(userOp) {
149
+ return {
150
+ ...userOp,
151
+ signature: generateDummySignature(),
152
+ // Ensure paymasterAndData is set if not provided
153
+ paymasterAndData: userOp.paymasterAndData || '0x'
154
+ };
155
+ }
156
+ exports.createUserOpForEstimation = createUserOpForEstimation;
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "gokite-aa-sdk",
3
+ "version": "1.0.0",
4
+ "description": "Simple and clean Account Abstraction SDK for Gokite",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "prepublishOnly": "npm run build",
10
+ "example": "ts-node example.ts"
11
+ },
12
+ "files": [
13
+ "dist/**/*",
14
+ "README.md"
15
+ ],
16
+ "keywords": [
17
+ "account-abstraction",
18
+ "aa",
19
+ "eip-4337",
20
+ "ethereum",
21
+ "wallet",
22
+ "gokite"
23
+ ],
24
+ "dependencies": {
25
+ "ethers": "^6.0.0"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^20.0.0",
29
+ "typescript": "^5.0.0",
30
+ "ts-node": "^10.0.0"
31
+ },
32
+ "peerDependencies": {
33
+ "ethers": "^6.0.0"
34
+ },
35
+ "engines": {
36
+ "node": ">=16"
37
+ },
38
+ "license": "MIT"
39
+ }