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 ADDED
@@ -0,0 +1,141 @@
1
+ # Gokite AA SDK
2
+
3
+ Account Abstraction (EIP-4337) SDK for Gokite.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install gokite-aa-sdk
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { GokiteAASDK } from 'gokite-aa-sdk';
15
+ import { ethers } from 'ethers';
16
+
17
+ // Initialize SDK
18
+ const sdk = new GokiteAASDK(
19
+ 'kite_testnet',
20
+ 'https://rpc-testnet.gokite.ai',
21
+ 'http://localhost:14337/rpc/' // bundler URL
22
+ );
23
+
24
+ // Owner address (from your social login SDK)
25
+ const owner = '0x...';
26
+
27
+ // Get account address (can get aa wallet address even if the wallet is not deployed)
28
+ const accountAddress = sdk.getAccountAddress(owner);
29
+
30
+ // Sign function - integrate with your social login SDK
31
+ const signFunction = async (userOpHash: string): Promise<string> => {
32
+ // Use your preferred signing method (Particle, Privy, etc.)
33
+ return await signer.sign(ethers.getBytes(userOpHash));
34
+ };
35
+
36
+ // Send transaction
37
+ const userOpHash = await sdk.sendUserOperation(
38
+ owner,
39
+ {
40
+ target: '0x...',
41
+ value: ethers.parseEther('0.1'),
42
+ callData: '0x'
43
+ },
44
+ signFunction
45
+ );
46
+
47
+ // Wait for confirmation
48
+ const status = await sdk.pollUserOperationStatus(userOpHash);
49
+ console.log('Transaction status:', status);
50
+ ```
51
+
52
+ ## API Reference
53
+
54
+ ### GokiteAASDK
55
+
56
+ #### Constructor
57
+
58
+ ```typescript
59
+ new GokiteAASDK(network: string, rpcUrl: string, bundlerUrl?: string)
60
+ ```
61
+
62
+ #### Methods
63
+
64
+ - `getAccountAddress(owner: string, salt?: bigint): string` - Calculate account address
65
+ - `sendUserOperation(owner: string, request: UserOperationRequest | BatchUserOperationRequest, signFn: SignFunction, salt?: bigint, paymasterAddress?: string): Promise<string>` - Send transaction
66
+ - `pollUserOperationStatus(userOpHash: string, options: PollingOptions = {}): Promise<UserOperationStatus>` - Wait for confirmation
67
+ - `isAccountDeloyed(accountAddress: string): Promise<boolean>` - Check if account is deployed
68
+
69
+ ### Types
70
+
71
+ ```typescript
72
+ interface UserOperationRequest {
73
+ target: string;
74
+ value?: bigint;
75
+ callData: string;
76
+ }
77
+
78
+ interface BatchUserOperationRequest {
79
+ targets: string[];
80
+ values?: bigint[];
81
+ callDatas: string[];
82
+ }
83
+
84
+ interface SignFunction {
85
+ (userOpHash: string): Promise<string>;
86
+ }
87
+ ```
88
+
89
+ ## Examples
90
+
91
+ ### Single Transaction
92
+
93
+ ```typescript
94
+ const request = {
95
+ target: '0x...',
96
+ value: ethers.parseEther('0.1'),
97
+ callData: '0x'
98
+ };
99
+
100
+ const userOpHash = await sdk.sendUserOperation(owner, request, signFunction);
101
+ ```
102
+
103
+ ### Batch Transactions
104
+
105
+ ```typescript
106
+ const batchRequest = {
107
+ targets: ['0x...', '0x...'],
108
+ values: [ethers.parseEther('0.1'), 0n],
109
+ callDatas: ['0x', '0x...']
110
+ };
111
+
112
+ const userOpHash = await sdk.sendUserOperation(owner, batchRequest, signFunction);
113
+ ```
114
+
115
+ ### Integration with Particle
116
+
117
+ #### docs:
118
+
119
+ https://developers.particle.network/api-reference/auth/desktop-sdks/web#personal-signatures
120
+
121
+ ```typescript
122
+ // After configuring AuthCoreContextProvider and logging in
123
+ const { signMessage } = useEthereum();
124
+
125
+ const signFunction = async (userOpHash: string): Promise<string> => {
126
+ return await signMessage(userOpHash)
127
+ };
128
+ ```
129
+
130
+ ## Supported Networks
131
+
132
+ - **kite_testnet**: Kite Testnet (Chain ID: 2368)
133
+
134
+ ## Requirements
135
+
136
+ - Node.js >= 16
137
+ - ethers >= 6.0.0
138
+
139
+ ## License
140
+
141
+ MIT
@@ -0,0 +1,9 @@
1
+ export interface NetworkConfig {
2
+ chainId: number;
3
+ entryPoint: string;
4
+ accountFactory: string;
5
+ accountImplementation: string;
6
+ bundlerUrl?: string;
7
+ paymaster?: string;
8
+ }
9
+ export declare const NETWORKS: Record<string, NetworkConfig>;
package/dist/config.js ADDED
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NETWORKS = void 0;
4
+ exports.NETWORKS = {
5
+ kite_testnet: {
6
+ chainId: 2368,
7
+ entryPoint: '0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108',
8
+ accountFactory: '0xF0Fc19F0dc393867F19351d25EDfc5E099561cb7',
9
+ accountImplementation: '0x93F5310eFd0f09db0666CA5146E63CA6Cdc6FC21',
10
+ paymaster: '0x122E0e1F7fFc0f5d64F5470CF42c6bA0abdF7158',
11
+ },
12
+ };
@@ -0,0 +1,47 @@
1
+ import { GokiteAASDK } from './gokite-aa-sdk';
2
+ import "dotenv/config";
3
+ declare function handleAAError(error: any): {
4
+ type: string;
5
+ message: string;
6
+ details?: any;
7
+ };
8
+ /**
9
+ * ClientAgentVault Integration Tests
10
+ *
11
+ * these tests show how to use the AA wallet to:
12
+ * 1. deploy the ClientAgentVault proxy contract (via performCreate)
13
+ * 2. configure spending rules (Spending Rules)
14
+ * 3. view spending rules (read-only)
15
+ * 4. withdraw funds (withdrawFunds)
16
+ * 5. check token balance (read-only)
17
+ *
18
+ * how to use:
19
+ * - modify the contract addresses and parameters as needed
20
+ */
21
+ declare function clientAgentVaultIntegrationTests(): Promise<void>;
22
+ /**
23
+ * Test 1: Deploy ClientAgentVault Proxy via AA wallet's performCreate
24
+ */
25
+ declare function DeployClientAgentVaultProxy(sdk: GokiteAASDK, eoa: string, aa: string, signFunction: any): Promise<string | null>;
26
+ /**
27
+ * Test 2: Configure Spending Rules
28
+ */
29
+ declare function ConfigureSpendingRules(sdk: GokiteAASDK, owner: string, proxyAddress: string, signFunction: any): Promise<void>;
30
+ /**
31
+ * Test 3: View Spending Rules (Read-only, no transaction sent)
32
+ */
33
+ declare function ViewSpendingRules(sdk: GokiteAASDK, proxyAddress: string): Promise<void>;
34
+ /**
35
+ * Test 4: Withdraw Funds
36
+ */
37
+ declare function WithdrawFunds(sdk: GokiteAASDK, owner: string, proxyAddress: string, signFunction: any): Promise<void>;
38
+ /**
39
+ * Test 5: Check Token Balance (Read-only)
40
+ */
41
+ declare function CheckTokenBalance(sdk: GokiteAASDK, proxyAddress: string): Promise<void>;
42
+ /**
43
+ * Legacy example for basic AA operations
44
+ */
45
+ declare function basicExample(): Promise<void>;
46
+ export { clientAgentVaultIntegrationTests, basicExample, DeployClientAgentVaultProxy, ConfigureSpendingRules, ViewSpendingRules, WithdrawFunds, CheckTokenBalance, handleAAError, };
47
+ export declare const example: typeof basicExample;
@@ -0,0 +1,397 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.example = exports.handleAAError = exports.CheckTokenBalance = exports.WithdrawFunds = exports.ViewSpendingRules = exports.ConfigureSpendingRules = exports.DeployClientAgentVaultProxy = exports.basicExample = exports.clientAgentVaultIntegrationTests = void 0;
4
+ const gokite_aa_sdk_1 = require("./gokite-aa-sdk");
5
+ const types_1 = require("./types");
6
+ const ethers_1 = require("ethers");
7
+ require("dotenv/config");
8
+ // Contract addresses on kite_testnet
9
+ const ADDRESSES = {
10
+ SETTLEMENT_TOKEN: '0x0fF5393387ad2f9f691FD6Fd28e07E3969e27e63',
11
+ SETTLEMENT_CONTRACT: '0x8d9FaD78d5Ce247aA01C140798B9558fd64a63E3',
12
+ CLIENT_AGENT_VAULT_IMPL: '0xB5AAFCC6DD4DFc2B80fb8BCcf406E1a2Fd559e23'
13
+ };
14
+ function handleAAError(error) {
15
+ if (error instanceof types_1.AASDKError) {
16
+ return {
17
+ type: error.type,
18
+ message: error.message,
19
+ details: error.details
20
+ };
21
+ }
22
+ // Fallback for other errors
23
+ return {
24
+ type: 'UNKNOWN_ERROR',
25
+ message: error.message || 'An unknown error occurred',
26
+ details: error
27
+ };
28
+ }
29
+ exports.handleAAError = handleAAError;
30
+ /**
31
+ * Get TransparentUpgradeableProxy bytecode
32
+ */
33
+ function getTransparentProxyBytecode() {
34
+ // This is the bytecode for TransparentUpgradeableProxy
35
+ return '0x60a0604052610b278038038061001481610293565b928339810160608282031261028e5761002c826102b8565b610038602084016102b8565b604084015190936001600160401b03821161028e570182601f8201121561028e5780519061006d610068836102cc565b610293565b938285526020838301011161028e5760005b828110610279575050602060009184010152803b15610258577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0383169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a281511561023f5760008083602061013595519101845af43d15610237573d91610125610068846102cc565b9283523d6000602085013e6102e7565b505b604051906104918083016001600160401b0381118482101761022157602092849261067684396001600160a01b031681520301906000f080156102155760018060a01b031680608052600080516020610b07833981519152547f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6040805160018060a01b0384168152846020820152a181156101ff576001600160a01b03191617600080516020610b078339815191525560405161032d908161034982396080518160070152f35b633173bdd160e11b600052600060045260246000fd5b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b6060916102e7565b505034156101375763b398979f60e01b60005260046000fd5b634c9c8ce360e01b60009081526001600160a01b0391909116600452602490fd5b8060208092840101518282880101520161007f565b600080fd5b6040519190601f01601f191682016001600160401b0381118382101761022157604052565b51906001600160a01b038216820361028e57565b6001600160401b03811161022157601f01601f191660200190565b9061030d57508051156102fc57805190602001fd5b630a12f52160e11b60005260046000fd5b8151158061033f575b61031e575090565b639996b31560e01b60009081526001600160a01b0391909116600452602490fd5b50803b1561031656fe6080604052337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031603610069576000356001600160e01b03191663278f794360e11b1461005f576334ad5dbb60e21b60005260046000fd5b610067610113565b005b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5460009081906001600160a01b0316368280378136915af43d6000803e156100b1573d6000f35b3d6000fd5b634e487b7160e01b600052604160045260246000fd5b6040519190601f01601f1916820167ffffffffffffffff8111838210176100f257604052565b6100b6565b67ffffffffffffffff81116100f257601f01601f191660200190565b3660041161019d57604036600319011261019d576004356001600160a01b0381169081900361019d576024359067ffffffffffffffff821161019d573660238301121561019d5781600401359061017161016c836100f7565b6100cc565b91808352366024828601011161019d57602081600092602461019b970183870137840101526101a2565b565b600080fd5b90813b15610239577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a280511561021f5761021c9161025b565b50565b50503461022857565b63b398979f60e01b60005260046000fd5b50634c9c8ce360e01b60009081526001600160a01b0391909116600452602490fd5b60008061028f93602081519101845af43d15610292573d9161027f61016c846100f7565b9283523d6000602085013e610296565b90565b6060915b906102bc57508051156102ab57805190602001fd5b630a12f52160e11b60005260046000fd5b815115806102ee575b6102cd575090565b639996b31560e01b60009081526001600160a01b0391909116600452602490fd5b50803b156102c556fea2646970667358221220597147005a6fe654561cbab25a93153cc233180473a65a90bd427f0c1f41018764736f6c634300081c003360803460bc57601f61049138819003918201601f19168301916001600160401b0383118484101760c15780849260209460405283398101031260bc57516001600160a01b0381169081900360bc57801560a657600080546001600160a01b031981168317825560405192916001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a36103b990816100d88239f35b631e4fbdf760e01b600052600060045260246000fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c8063715018a6146102875780638da5cb5b146102605780639623609d1461012f578063ad3cb1cc146100e25763f2fde38b1461005457600080fd5b346100df5760203660031901126100df576004356001600160a01b038116908190036100dd5761008261035a565b80156100c95781546001600160a01b03198116821783556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b631e4fbdf760e01b82526004829052602482fd5b505b80fd5b50346100df57806003193601126100df575061012b6040516101056040826102e1565b60058152640352e302e360dc1b6020820152604051918291602083526020830190610319565b0390f35b5060603660031901126100df576004356001600160a01b038116908190036100dd576024356001600160a01b038116908190036102405760443567ffffffffffffffff811161025c573660238201121561025c57806004013567ffffffffffffffff8111610248576040518593929091906101b4601f8301601f1916602001846102e1565b81835236602483830101116102445781859260246020930183860137830101526101dc61035a565b833b156102405761021293839260405180968194829363278f794360e11b84526004840152604060248401526044830190610319565b039134905af18015610233576102255780f35b61022e916102e1565b388180f35b50604051903d90823e3d90fd5b8280fd5b8480fd5b634e487b7160e01b85526041600452602485fd5b8380fd5b50346100df57806003193601126100df57546040516001600160a01b039091168152602090f35b50346100df57806003193601126100df576102a061035a565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b90601f8019910116810190811067ffffffffffffffff82111761030357604052565b634e487b7160e01b600052604160045260246000fd5b919082519283825260005b848110610345575050826000602080949584010152601f8019910116010190565b80602080928401015182828601015201610324565b6000546001600160a01b0316330361036e57565b63118cdaa760e01b6000523360045260246000fdfea26469706673582212207bc32ec723f6be34b228b59aef2ef61b4e6a8eb5bc67fcdd495248566e3b6e0c64736f6c634300081c0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103';
36
+ }
37
+ /**
38
+ * ClientAgentVault Integration Tests
39
+ *
40
+ * these tests show how to use the AA wallet to:
41
+ * 1. deploy the ClientAgentVault proxy contract (via performCreate)
42
+ * 2. configure spending rules (Spending Rules)
43
+ * 3. view spending rules (read-only)
44
+ * 4. withdraw funds (withdrawFunds)
45
+ * 5. check token balance (read-only)
46
+ *
47
+ * how to use:
48
+ * - modify the contract addresses and parameters as needed
49
+ */
50
+ async function clientAgentVaultIntegrationTests() {
51
+ console.log('\n=== ClientAgentVault Integration Tests ===');
52
+ // Initialize SDK
53
+ const sdk = new gokite_aa_sdk_1.GokiteAASDK('kite_testnet', 'https://rpc-testnet.gokite.ai', 'http://localhost:14337/rpc/');
54
+ // user's EOA address and AA wallet address
55
+ const eoa = '0x4A50DCA63d541372ad36E5A36F1D542d51164F19';
56
+ const aa = sdk.getAccountAddress(eoa);
57
+ console.log('AA Wallet Address:', aa);
58
+ // Sign function, replace with particle or privy sdk
59
+ const signFunction = async (userOpHash) => {
60
+ const signer_pk = process.env.PRIVATE_KEY;
61
+ const signer = new ethers_1.ethers.Wallet(signer_pk);
62
+ return signer.signMessage(ethers_1.ethers.getBytes(userOpHash));
63
+ };
64
+ // 1. Deploy ClientAgentVault Proxy via performCreate
65
+ console.log('\n--- Test 1: Deploy ClientAgentVault Proxy ---');
66
+ const deployedProxyAddress = await DeployClientAgentVaultProxy(sdk, eoa, aa, signFunction);
67
+ if (!deployedProxyAddress) {
68
+ console.log('❌ Failed to deploy proxy, cannot continue with other tests');
69
+ return;
70
+ }
71
+ console.log(`✅ Using deployed proxy address: ${deployedProxyAddress}`);
72
+ // 2. Configure Spending Rules
73
+ console.log('\n--- Test 2: Configure Spending Rules ---');
74
+ await ConfigureSpendingRules(sdk, eoa, deployedProxyAddress, signFunction);
75
+ // 3. View Spending Rules
76
+ console.log('\n--- Test 3: View Spending Rules ---');
77
+ await ViewSpendingRules(sdk, deployedProxyAddress);
78
+ // 4. Withdraw Funds
79
+ console.log('\n--- Test 4: Withdraw Funds ---');
80
+ await WithdrawFunds(sdk, eoa, deployedProxyAddress, signFunction);
81
+ // 5. Check Token Balance
82
+ console.log('\n--- Test 5: Check Token Balance ---');
83
+ await CheckTokenBalance(sdk, deployedProxyAddress);
84
+ }
85
+ exports.clientAgentVaultIntegrationTests = clientAgentVaultIntegrationTests;
86
+ /**
87
+ * Test 1: Deploy ClientAgentVault Proxy via AA wallet's performCreate
88
+ */
89
+ async function DeployClientAgentVaultProxy(sdk, eoa, aa, signFunction) {
90
+ try {
91
+ // Prepare initialization data for ClientAgentVault
92
+ const initializeCallData = ethers_1.ethers.Interface.from([
93
+ 'function initialize(address allowedToken, address owner)'
94
+ ]).encodeFunctionData('initialize', [
95
+ ADDRESSES.SETTLEMENT_TOKEN,
96
+ aa // owner (AA wallet address)
97
+ ]);
98
+ // Create TransparentUpgradeableProxy deployment bytecode
99
+ // constructor(address _logic, address admin_, bytes memory _data)
100
+ const proxyConstructorData = ethers_1.ethers.AbiCoder.defaultAbiCoder().encode(['address', 'address', 'bytes'], [
101
+ ADDRESSES.CLIENT_AGENT_VAULT_IMPL,
102
+ aa,
103
+ initializeCallData // initialization data
104
+ ]);
105
+ // Full deployment bytecode = creation code + constructor params
106
+ const transparentProxyBytecode = getTransparentProxyBytecode();
107
+ const fullInitCode = transparentProxyBytecode + proxyConstructorData.slice(2);
108
+ // Create UserOperation to call performCreate
109
+ const deployRequest = {
110
+ target: aa,
111
+ value: 0n,
112
+ callData: ethers_1.ethers.Interface.from([
113
+ 'function performCreate(uint256 value, bytes calldata initCode) returns (address)'
114
+ ]).encodeFunctionData('performCreate', [
115
+ 0n,
116
+ fullInitCode // proxy deployment bytecode + constructor params
117
+ ])
118
+ };
119
+ console.log('Deploying ClientAgentVault proxy...');
120
+ console.log('- Implementation:', ADDRESSES.CLIENT_AGENT_VAULT_IMPL);
121
+ console.log('- AllowedToken:', ADDRESSES.SETTLEMENT_TOKEN);
122
+ const result = await sdk.sendUserOperationAndWait(eoa, deployRequest, signFunction);
123
+ if (result.status.status === 'success') {
124
+ console.log('✅ Proxy deployed successfully!');
125
+ console.log('Transaction hash:', result.status.transactionHash);
126
+ // Parse the deployed proxy address from transaction logs
127
+ const proxyAddress = await parseContractCreatedEvent(result.status.transactionHash);
128
+ if (proxyAddress) {
129
+ console.log('🎯 Deployed proxy address:', proxyAddress);
130
+ return proxyAddress; // Return the actual proxy address
131
+ }
132
+ else {
133
+ console.log('⚠️ Could not parse proxy address from logs');
134
+ }
135
+ }
136
+ else {
137
+ console.log('❌ Deployment failed:', result.status.reason);
138
+ }
139
+ }
140
+ catch (error) {
141
+ console.error('❌ Test 1 failed:', error);
142
+ }
143
+ return null;
144
+ }
145
+ exports.DeployClientAgentVaultProxy = DeployClientAgentVaultProxy;
146
+ /**
147
+ * Test 2: Configure Spending Rules
148
+ */
149
+ async function ConfigureSpendingRules(sdk, owner, proxyAddress, signFunction) {
150
+ // get today's 00:00:00 timestamp
151
+ const today = new Date();
152
+ const todayStart = new Date(today.getFullYear(), today.getMonth(), today.getDate());
153
+ const todayStartTimestamp = Math.floor(todayStart.getTime() / 1000);
154
+ // get current week's monday 00:00:00 timestamp
155
+ const dayOfWeek = today.getDay(); // 0=Sunday, 1=Monday, ..., 6=Saturday
156
+ const daysFromMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1; // Convert Sunday=0 to Sunday=6
157
+ const currentWeekStartTimestamp = todayStartTimestamp - (daysFromMonday * 86400); // 86400 = seconds in a day
158
+ // rules fields:
159
+ // - TimeWindow: time window in seconds, 0 means per transaction, >0 means per time window
160
+ // - Budget: budget in wei, 18 decimals, like 1e18 means 1 token
161
+ // - InitialWindowStartTime: start time of the time window in unix timestamp
162
+ // should be set to the start time of the day/week/month in local time (or utc) 00:00:00
163
+ // - TargetProviders: target service providers array, empty array means applies to all providers
164
+ try {
165
+ // Define spending rules
166
+ const rulesToAdd = [
167
+ {
168
+ timeWindow: 86400n,
169
+ budget: ethers_1.ethers.parseUnits('100', 18),
170
+ initialWindowStartTime: todayStartTimestamp,
171
+ targetProviders: [] // Empty means applies to all providers
172
+ },
173
+ {
174
+ timeWindow: 604800n,
175
+ budget: ethers_1.ethers.parseUnits('1000', 18),
176
+ initialWindowStartTime: currentWeekStartTimestamp,
177
+ targetProviders: []
178
+ },
179
+ {
180
+ timeWindow: 0,
181
+ budget: ethers_1.ethers.parseUnits('10', 18),
182
+ initialWindowStartTime: 0n,
183
+ targetProviders: [ethers_1.ethers.keccak256(ethers_1.ethers.toUtf8Bytes('provider1'))]
184
+ }
185
+ ];
186
+ const configureRequest = {
187
+ target: proxyAddress,
188
+ value: 0n,
189
+ callData: ethers_1.ethers.Interface.from([
190
+ 'function configureSpendingRule(uint256[] calldata indicesToRemove, tuple(uint256 timeWindow, uint160 budget, uint96 initialWindowStartTime, bytes32[] targetProviders)[] calldata rulesToAdd)'
191
+ ]).encodeFunctionData('configureSpendingRule', [
192
+ [],
193
+ rulesToAdd // rules to add
194
+ ])
195
+ };
196
+ console.log('Configuring spending rules...');
197
+ console.log('- Rule 1: 100 tokens per 24 hours (all providers)');
198
+ console.log('- Rule 2: 10 tokens per hour (specific provider)');
199
+ const result = await sdk.sendUserOperationAndWait(owner, configureRequest, signFunction);
200
+ if (result.status.status === 'success') {
201
+ console.log('✅ Spending rules configured successfully!');
202
+ console.log('Transaction hash:', result.status.transactionHash);
203
+ }
204
+ else {
205
+ console.log('❌ Configuration failed:', result.status.reason);
206
+ }
207
+ }
208
+ catch (error) {
209
+ const aaError = handleAAError(error);
210
+ console.error('❌ Test 2 failed:', {
211
+ type: aaError.type,
212
+ message: aaError.message
213
+ });
214
+ // Frontend can handle different error types
215
+ switch (aaError.type) {
216
+ case 'ESTIMATE_GAS_FAILED':
217
+ console.log('Suggestion: Check if the contract call is valid');
218
+ break;
219
+ case 'SEND_USEROP_FAILED':
220
+ console.log('Suggestion: Try again or check bundler status');
221
+ break;
222
+ case 'NETWORK_ERROR':
223
+ console.log('Suggestion: Check your internet connection');
224
+ break;
225
+ default:
226
+ console.log('Suggestion: Check console for more details');
227
+ }
228
+ }
229
+ }
230
+ exports.ConfigureSpendingRules = ConfigureSpendingRules;
231
+ /**
232
+ * Test 3: View Spending Rules (Read-only, no transaction sent)
233
+ */
234
+ async function ViewSpendingRules(sdk, proxyAddress) {
235
+ try {
236
+ const provider = new ethers_1.ethers.JsonRpcProvider('https://rpc-testnet.gokite.ai');
237
+ const contract = new ethers_1.ethers.Contract(proxyAddress, [
238
+ 'function getSpendingRules() view returns (tuple(tuple(uint256 timeWindow, uint160 budget, uint96 initialWindowStartTime, bytes32[] targetProviders) rule, tuple(uint128 amountUsed, uint128 currentTimeWindowStartTime) usage)[])'
239
+ ], provider);
240
+ console.log('Fetching spending rules...');
241
+ const spendingRules = await contract.getSpendingRules();
242
+ console.log('✅ Spending Rules:');
243
+ spendingRules.forEach((rule, index) => {
244
+ console.log(` Rule ${index + 1}:`);
245
+ console.log(` - Time Window: ${rule.rule.timeWindow} seconds`);
246
+ console.log(` - Budget: ${ethers_1.ethers.formatUnits(rule.rule.budget, 18)} tokens`);
247
+ console.log(` - Used: ${ethers_1.ethers.formatUnits(rule.usage.amountUsed, 18)} tokens`);
248
+ console.log(` - Providers: ${rule.rule.targetProviders.length === 0 ? 'All' : rule.rule.targetProviders.length}`);
249
+ });
250
+ }
251
+ catch (error) {
252
+ console.error('❌ Test 3 failed:', error);
253
+ }
254
+ }
255
+ exports.ViewSpendingRules = ViewSpendingRules;
256
+ /**
257
+ * Test 4: Withdraw Funds
258
+ */
259
+ async function WithdrawFunds(sdk, owner, proxyAddress, signFunction) {
260
+ try {
261
+ const withdrawAmount = ethers_1.ethers.parseUnits('50', 18); // Withdraw 50 tokens
262
+ const withdrawRequest = {
263
+ target: proxyAddress,
264
+ value: 0n,
265
+ callData: ethers_1.ethers.Interface.from([
266
+ 'function withdrawFunds(address token, uint256 amount)'
267
+ ]).encodeFunctionData('withdrawFunds', [
268
+ ADDRESSES.SETTLEMENT_TOKEN,
269
+ withdrawAmount // amount to withdraw
270
+ ])
271
+ };
272
+ console.log('Withdrawing funds...');
273
+ console.log(`- Token: ${ADDRESSES.SETTLEMENT_TOKEN}`);
274
+ console.log(`- Amount: ${ethers_1.ethers.formatUnits(withdrawAmount, 18)} tokens`);
275
+ const result = await sdk.sendUserOperationAndWait(owner, withdrawRequest, signFunction);
276
+ if (result.status.status === 'success') {
277
+ console.log('✅ Funds withdrawn successfully!');
278
+ console.log('Transaction hash:', result.status.transactionHash);
279
+ }
280
+ else {
281
+ console.log('❌ Withdrawal failed:', result.status.reason);
282
+ }
283
+ }
284
+ catch (error) {
285
+ console.error('❌ Test 4 failed:', error);
286
+ }
287
+ }
288
+ exports.WithdrawFunds = WithdrawFunds;
289
+ /**
290
+ * Test 5: Check Token Balance (Read-only)
291
+ */
292
+ async function CheckTokenBalance(sdk, proxyAddress) {
293
+ try {
294
+ const provider = new ethers_1.ethers.JsonRpcProvider('https://rpc-testnet.gokite.ai');
295
+ const tokenContract = new ethers_1.ethers.Contract(ADDRESSES.SETTLEMENT_TOKEN, [
296
+ 'function balanceOf(address account) view returns (uint256)',
297
+ 'function symbol() view returns (string)',
298
+ 'function decimals() view returns (uint8)'
299
+ ], provider);
300
+ console.log('Checking token balance...');
301
+ const [balance, symbol, decimals] = await Promise.all([
302
+ tokenContract.balanceOf(proxyAddress),
303
+ tokenContract.symbol(),
304
+ tokenContract.decimals()
305
+ ]);
306
+ console.log('✅ Token Balance:');
307
+ console.log(` - Address: ${proxyAddress}`);
308
+ console.log(` - Token: ${symbol} (${ADDRESSES.SETTLEMENT_TOKEN})`);
309
+ console.log(` - Balance: ${ethers_1.ethers.formatUnits(balance, decimals)} ${symbol}`);
310
+ }
311
+ catch (error) {
312
+ console.error('❌ Test 5 failed:', error);
313
+ }
314
+ }
315
+ exports.CheckTokenBalance = CheckTokenBalance;
316
+ /**
317
+ * Legacy example for basic AA operations
318
+ */
319
+ async function basicExample() {
320
+ console.log('\n=== Basic AA SDK Example ===');
321
+ // Initialize SDK
322
+ const sdk = new gokite_aa_sdk_1.GokiteAASDK('kite_testnet', 'https://rpc-testnet.gokite.ai', 'http://localhost:14337/rpc/');
323
+ const owner = '0x4A50DCA63d541372ad36E5A36F1D542d51164F19';
324
+ const accountAddress = sdk.getAccountAddress(owner);
325
+ console.log('Account address:', accountAddress);
326
+ // Simple ETH transfer example
327
+ const sendEthRequest = {
328
+ target: '0x4A50DCA63d541372ad36E5A36F1D542d51164F19',
329
+ value: ethers_1.ethers.parseEther('0.001'),
330
+ callData: '0x'
331
+ };
332
+ const signFunction = async (userOpHash) => {
333
+ const signer_pk = process.env.PRIVATE_KEY;
334
+ const signer = new ethers_1.ethers.Wallet(signer_pk);
335
+ return signer.signMessage(ethers_1.ethers.getBytes(userOpHash));
336
+ };
337
+ try {
338
+ const result = await sdk.sendUserOperationAndWait(owner, sendEthRequest, signFunction);
339
+ if (result.status.status === 'success') {
340
+ console.log('✅ ETH transfer successful!');
341
+ console.log('Transaction hash:', result.status.transactionHash);
342
+ }
343
+ else {
344
+ console.log('❌ ETH transfer failed:', result.status.reason);
345
+ }
346
+ }
347
+ catch (error) {
348
+ console.error('❌ Basic example failed:', error);
349
+ }
350
+ }
351
+ exports.basicExample = basicExample;
352
+ /**
353
+ * Parse ContractCreated event from transaction logs to get deployed proxy address
354
+ * Event: ContractCreated(address indexed contractAddress)
355
+ */
356
+ async function parseContractCreatedEvent(transactionHash) {
357
+ try {
358
+ const provider = new ethers_1.ethers.JsonRpcProvider('https://rpc-testnet.gokite.ai');
359
+ const receipt = await provider.getTransactionReceipt(transactionHash);
360
+ if (!receipt) {
361
+ console.error('Transaction receipt not found');
362
+ return null;
363
+ }
364
+ // ContractCreated event signature: ContractCreated(address indexed contractAddress)
365
+ const contractCreatedEventSignature = ethers_1.ethers.id('ContractCreated(address)');
366
+ console.log('Parsing transaction logs...');
367
+ console.log(`Total logs: ${receipt.logs.length}`);
368
+ for (const log of receipt.logs) {
369
+ // Check if this log matches the ContractCreated event
370
+ if (log.topics[0] === contractCreatedEventSignature) {
371
+ // The first topic is the event signature
372
+ // The second topic is the indexed contractAddress
373
+ const contractAddress = ethers_1.ethers.AbiCoder.defaultAbiCoder().decode(['address'], log.topics[1])[0];
374
+ console.log('Found ContractCreated event:');
375
+ console.log('- Contract Address:', contractAddress);
376
+ console.log('- From Address:', log.address);
377
+ return contractAddress;
378
+ }
379
+ }
380
+ console.log('No ContractCreated event found in transaction logs');
381
+ return null;
382
+ }
383
+ catch (error) {
384
+ console.error('Error parsing ContractCreated event:', error);
385
+ return null;
386
+ }
387
+ }
388
+ async function main() {
389
+ // Run ClientAgentVault integration tests
390
+ await clientAgentVaultIntegrationTests();
391
+ // // Run basic AA example
392
+ // await basicExample();
393
+ console.log('\n✅ All examples completed!');
394
+ }
395
+ // Legacy export for backwards compatibility
396
+ exports.example = basicExample;
397
+ main().catch(console.error);