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/README.md +141 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.js +12 -0
- package/dist/example.d.ts +47 -0
- package/dist/example.js +397 -0
- package/dist/gokite-aa-sdk.d.ts +70 -0
- package/dist/gokite-aa-sdk.js +428 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +23 -0
- package/dist/types.d.ts +95 -0
- package/dist/types.js +13 -0
- package/dist/utils.d.ts +49 -0
- package/dist/utils.js +156 -0
- package/package.json +39 -0
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
|
+
}
|