@turnkey/gas-station 0.2.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.
Files changed (45) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +726 -0
  3. package/dist/abi/gas-station.d.ts +546 -0
  4. package/dist/abi/gas-station.d.ts.map +1 -0
  5. package/dist/abi/gas-station.js +275 -0
  6. package/dist/abi/gas-station.js.map +1 -0
  7. package/dist/abi/gas-station.mjs +273 -0
  8. package/dist/abi/gas-station.mjs.map +1 -0
  9. package/dist/config.d.ts +44 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +57 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/config.mjs +51 -0
  14. package/dist/config.mjs.map +1 -0
  15. package/dist/gasStationClient.d.ts +71 -0
  16. package/dist/gasStationClient.d.ts.map +1 -0
  17. package/dist/gasStationClient.js +237 -0
  18. package/dist/gasStationClient.js.map +1 -0
  19. package/dist/gasStationClient.mjs +235 -0
  20. package/dist/gasStationClient.mjs.map +1 -0
  21. package/dist/gasStationUtils.d.ts +7069 -0
  22. package/dist/gasStationUtils.d.ts.map +1 -0
  23. package/dist/gasStationUtils.js +129 -0
  24. package/dist/gasStationUtils.js.map +1 -0
  25. package/dist/gasStationUtils.mjs +120 -0
  26. package/dist/gasStationUtils.mjs.map +1 -0
  27. package/dist/index.d.ts +8 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +29 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/index.mjs +6 -0
  32. package/dist/index.mjs.map +1 -0
  33. package/dist/intentBuilder.d.ts +61 -0
  34. package/dist/intentBuilder.d.ts.map +1 -0
  35. package/dist/intentBuilder.js +153 -0
  36. package/dist/intentBuilder.js.map +1 -0
  37. package/dist/intentBuilder.mjs +151 -0
  38. package/dist/intentBuilder.mjs.map +1 -0
  39. package/dist/policyUtils.d.ts +271 -0
  40. package/dist/policyUtils.d.ts.map +1 -0
  41. package/dist/policyUtils.js +387 -0
  42. package/dist/policyUtils.js.map +1 -0
  43. package/dist/policyUtils.mjs +381 -0
  44. package/dist/policyUtils.mjs.map +1 -0
  45. package/package.json +47 -0
package/dist/config.js ADDED
@@ -0,0 +1,57 @@
1
+ 'use strict';
2
+
3
+ var chains = require('viem/chains');
4
+
5
+ // Default contract addresses (deterministically deployed across all chains)
6
+ const DEFAULT_DELEGATE_CONTRACT = "0xC2a37Ee08cAc3778d9d05FF0a93FD5B553C77E3a";
7
+ const DEFAULT_EXECUTION_CONTRACT = "0x4ece92b06C7d2d99d87f052E0Fca47Fb180c3348";
8
+ // Chain preset configurations
9
+ const CHAIN_PRESETS = {
10
+ BASE_MAINNET: {
11
+ chain: chains.base,
12
+ rpcUrl: process.env.BASE_RPC_URL || "",
13
+ tokens: {
14
+ USDC: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
15
+ },
16
+ },
17
+ ETHEREUM_MAINNET: {
18
+ chain: chains.mainnet,
19
+ rpcUrl: process.env.ETH_RPC_URL || "",
20
+ tokens: {
21
+ USDC: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
22
+ },
23
+ },
24
+ SEPOLIA: {
25
+ chain: chains.sepolia,
26
+ rpcUrl: process.env.SEPOLIA_RPC_URL || "",
27
+ },
28
+ };
29
+ /**
30
+ * Create a custom preset with validation
31
+ */
32
+ function createCustomPreset(config) {
33
+ if (!config.chain) {
34
+ throw new Error("Chain configuration is required");
35
+ }
36
+ if (!config.rpcUrl) {
37
+ throw new Error("RPC URL is required");
38
+ }
39
+ return config;
40
+ }
41
+ /**
42
+ * Get a preset with optional environment variable overrides
43
+ */
44
+ function getPreset(presetName, overrides) {
45
+ const preset = CHAIN_PRESETS[presetName];
46
+ if (!preset) {
47
+ throw new Error(`Unknown preset: ${presetName}. Available: ${Object.keys(CHAIN_PRESETS).join(", ")}`);
48
+ }
49
+ return { ...preset, ...overrides };
50
+ }
51
+
52
+ exports.CHAIN_PRESETS = CHAIN_PRESETS;
53
+ exports.DEFAULT_DELEGATE_CONTRACT = DEFAULT_DELEGATE_CONTRACT;
54
+ exports.DEFAULT_EXECUTION_CONTRACT = DEFAULT_EXECUTION_CONTRACT;
55
+ exports.createCustomPreset = createCustomPreset;
56
+ exports.getPreset = getPreset;
57
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sources":["../src/config.ts"],"sourcesContent":[null],"names":["base","mainnet","sepolia"],"mappings":";;;;AAGA;AACO,MAAM,yBAAyB,GACpC;AACK,MAAM,0BAA0B,GACrC;AAsCF;AACO,MAAM,aAAa,GAAgC;AACxD,IAAA,YAAY,EAAE;AACZ,QAAA,KAAK,EAAEA,WAAI;AACX,QAAA,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE;AACtC,QAAA,MAAM,EAAE;AACN,YAAA,IAAI,EAAE,4CAA4C;AACnD,SAAA;AACF,KAAA;AACD,IAAA,gBAAgB,EAAE;AAChB,QAAA,KAAK,EAAEC,cAAO;AACd,QAAA,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE;AACrC,QAAA,MAAM,EAAE;AACN,YAAA,IAAI,EAAE,4CAA4C;AACnD,SAAA;AACF,KAAA;AACD,IAAA,OAAO,EAAE;AACP,QAAA,KAAK,EAAEC,cAAO;AACd,QAAA,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE;AAC1C,KAAA;;AAGH;;AAEG;AACG,SAAU,kBAAkB,CAAC,MAAmB,EAAA;AACpD,IAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;AACjB,QAAA,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC;IACpD;AACA,IAAA,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;AAClB,QAAA,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC;IACxC;AACA,IAAA,OAAO,MAAM;AACf;AAEA;;AAEG;AACG,SAAU,SAAS,CACvB,UAAsC,EACtC,SAAgC,EAAA;AAEhC,IAAA,MAAM,MAAM,GAAG,aAAa,CAAC,UAAU,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE;AACX,QAAA,MAAM,IAAI,KAAK,CACb,mBAAmB,UAAU,CAAA,aAAA,EAAgB,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA,CAAE,CACrF;IACH;AACA,IAAA,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,SAAS,EAAE;AACpC;;;;;;;;"}
@@ -0,0 +1,51 @@
1
+ import { sepolia, mainnet, base } from 'viem/chains';
2
+
3
+ // Default contract addresses (deterministically deployed across all chains)
4
+ const DEFAULT_DELEGATE_CONTRACT = "0xC2a37Ee08cAc3778d9d05FF0a93FD5B553C77E3a";
5
+ const DEFAULT_EXECUTION_CONTRACT = "0x4ece92b06C7d2d99d87f052E0Fca47Fb180c3348";
6
+ // Chain preset configurations
7
+ const CHAIN_PRESETS = {
8
+ BASE_MAINNET: {
9
+ chain: base,
10
+ rpcUrl: process.env.BASE_RPC_URL || "",
11
+ tokens: {
12
+ USDC: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
13
+ },
14
+ },
15
+ ETHEREUM_MAINNET: {
16
+ chain: mainnet,
17
+ rpcUrl: process.env.ETH_RPC_URL || "",
18
+ tokens: {
19
+ USDC: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
20
+ },
21
+ },
22
+ SEPOLIA: {
23
+ chain: sepolia,
24
+ rpcUrl: process.env.SEPOLIA_RPC_URL || "",
25
+ },
26
+ };
27
+ /**
28
+ * Create a custom preset with validation
29
+ */
30
+ function createCustomPreset(config) {
31
+ if (!config.chain) {
32
+ throw new Error("Chain configuration is required");
33
+ }
34
+ if (!config.rpcUrl) {
35
+ throw new Error("RPC URL is required");
36
+ }
37
+ return config;
38
+ }
39
+ /**
40
+ * Get a preset with optional environment variable overrides
41
+ */
42
+ function getPreset(presetName, overrides) {
43
+ const preset = CHAIN_PRESETS[presetName];
44
+ if (!preset) {
45
+ throw new Error(`Unknown preset: ${presetName}. Available: ${Object.keys(CHAIN_PRESETS).join(", ")}`);
46
+ }
47
+ return { ...preset, ...overrides };
48
+ }
49
+
50
+ export { CHAIN_PRESETS, DEFAULT_DELEGATE_CONTRACT, DEFAULT_EXECUTION_CONTRACT, createCustomPreset, getPreset };
51
+ //# sourceMappingURL=config.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.mjs","sources":["../src/config.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAGA;AACO,MAAM,yBAAyB,GACpC;AACK,MAAM,0BAA0B,GACrC;AAsCF;AACO,MAAM,aAAa,GAAgC;AACxD,IAAA,YAAY,EAAE;AACZ,QAAA,KAAK,EAAE,IAAI;AACX,QAAA,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE;AACtC,QAAA,MAAM,EAAE;AACN,YAAA,IAAI,EAAE,4CAA4C;AACnD,SAAA;AACF,KAAA;AACD,IAAA,gBAAgB,EAAE;AAChB,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE;AACrC,QAAA,MAAM,EAAE;AACN,YAAA,IAAI,EAAE,4CAA4C;AACnD,SAAA;AACF,KAAA;AACD,IAAA,OAAO,EAAE;AACP,QAAA,KAAK,EAAE,OAAO;AACd,QAAA,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE;AAC1C,KAAA;;AAGH;;AAEG;AACG,SAAU,kBAAkB,CAAC,MAAmB,EAAA;AACpD,IAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;AACjB,QAAA,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC;IACpD;AACA,IAAA,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;AAClB,QAAA,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC;IACxC;AACA,IAAA,OAAO,MAAM;AACf;AAEA;;AAEG;AACG,SAAU,SAAS,CACvB,UAAsC,EACtC,SAAgC,EAAA;AAEhC,IAAA,MAAM,MAAM,GAAG,aAAa,CAAC,UAAU,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE;AACX,QAAA,MAAM,IAAI,KAAK,CACb,mBAAmB,UAAU,CAAA,aAAA,EAAgB,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA,CAAE,CACrF;IACH;AACA,IAAA,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,SAAS,EAAE;AACpC;;;;"}
@@ -0,0 +1,71 @@
1
+ import { type SignedAuthorization } from "viem";
2
+ import type { GasStationConfig, ExecutionIntent } from "./config";
3
+ import { IntentBuilder } from "./intentBuilder";
4
+ export declare class GasStationClient {
5
+ private walletClient;
6
+ private publicClient;
7
+ private delegateContract;
8
+ private executionContract;
9
+ constructor(config: GasStationConfig);
10
+ /**
11
+ * Sign an EIP-7702 authorization to delegate control to the gas station contract
12
+ * Call this with an end-user client to get a signed authorization
13
+ * The authorization can then be submitted by the paymaster using submitAuthorization()
14
+ */
15
+ signAuthorization(): Promise<SignedAuthorization>;
16
+ /**
17
+ * Submit signed EIP-7702 authorization transaction(s)
18
+ * Supports authorizing multiple EOAs in a single transaction
19
+ * Call this with a paymaster client to broadcast the authorization transaction
20
+ * The paymaster pays for the gas
21
+ */
22
+ submitAuthorizations(authorizations: SignedAuthorization[]): Promise<{
23
+ txHash: `0x${string}`;
24
+ blockNumber: bigint;
25
+ }>;
26
+ /**
27
+ * Check if an EOA is delegated to the gas station contract
28
+ * If no address is provided, uses the signer's address
29
+ */
30
+ isAuthorized(eoaAddress?: `0x${string}`): Promise<boolean>;
31
+ /**
32
+ * Get the current nonce for an EOA address from the gas station contract
33
+ * If no address is provided, uses the signer's address
34
+ */
35
+ getNonce(eoaAddress?: `0x${string}`): Promise<bigint>;
36
+ /**
37
+ * Attempts to get the revert reason from a failed transaction.
38
+ * Replays the transaction via eth_call to extract detailed error information.
39
+ *
40
+ * This helps surface on-chain failure reasons such as:
41
+ * - Out of gas errors
42
+ * - Revert with reason strings
43
+ * - Custom error selectors
44
+ * - Insufficient balance errors
45
+ */
46
+ private getRevertReason;
47
+ /**
48
+ * Create an intent builder for composing complex transactions
49
+ * Call this with an end-user client to create intents for signing
50
+ */
51
+ createIntent(): IntentBuilder;
52
+ /**
53
+ * Sign an execution transaction for a signed intent (paymaster signs, doesn't send)
54
+ * This is useful for testing policies - the paymaster attempts to sign the execution
55
+ * but doesn't actually broadcast it to the network.
56
+ * Call this with a paymaster client to test if the paymaster can sign the execution.
57
+ */
58
+ signExecution(intent: ExecutionIntent): Promise<`0x${string}`>;
59
+ /**
60
+ * Execute a signed intent through the gas station contract.
61
+ * Packs the execution data according to the delegate contract's expected format and
62
+ * submits it via the execution contract.
63
+ * Call this with a paymaster client to submit and pay for the transaction.
64
+ */
65
+ execute(intent: ExecutionIntent): Promise<{
66
+ txHash: `0x${string}`;
67
+ blockNumber: bigint;
68
+ gasUsed: bigint;
69
+ }>;
70
+ }
71
+ //# sourceMappingURL=gasStationClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gasStationClient.d.ts","sourceRoot":"","sources":["../src/gasStationClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,mBAAmB,EAMzB,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAKlE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAMhD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,YAAY,CAA0C;IAC9D,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,gBAAgB,CAAgB;IACxC,OAAO,CAAC,iBAAiB,CAAgB;gBAE7B,MAAM,EAAE,gBAAgB;IAYpC;;;;OAIG;IACG,iBAAiB,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAUvD;;;;;OAKG;IACG,oBAAoB,CACxB,cAAc,EAAE,mBAAmB,EAAE,GACpC,OAAO,CAAC;QAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IA8B1D;;;OAGG;IACG,YAAY,CAAC,UAAU,CAAC,EAAE,KAAK,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAahE;;;OAGG;IACG,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAa3D;;;;;;;;;OASG;YACW,eAAe;IAkD7B;;;OAGG;IACH,YAAY,IAAI,aAAa;IAa7B;;;;;OAKG;IACG,aAAa,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC;IAkCpE;;;;;OAKG;IACG,OAAO,CACX,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC;QAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CA8C5E"}
@@ -0,0 +1,237 @@
1
+ 'use strict';
2
+
3
+ var viem = require('viem');
4
+ var gasStation = require('./abi/gas-station.js');
5
+ var config = require('./config.js');
6
+ var intentBuilder = require('./intentBuilder.js');
7
+ var gasStationUtils = require('./gasStationUtils.js');
8
+
9
+ class GasStationClient {
10
+ constructor(config$1) {
11
+ this.walletClient = config$1.walletClient;
12
+ this.publicClient = gasStationUtils.createPublicClientForChain(config$1.walletClient.chain, config$1.walletClient.transport.url);
13
+ this.delegateContract =
14
+ config$1.delegateContract ?? config.DEFAULT_DELEGATE_CONTRACT;
15
+ this.executionContract =
16
+ config$1.executionContract ?? config.DEFAULT_EXECUTION_CONTRACT;
17
+ }
18
+ /**
19
+ * Sign an EIP-7702 authorization to delegate control to the gas station contract
20
+ * Call this with an end-user client to get a signed authorization
21
+ * The authorization can then be submitted by the paymaster using submitAuthorization()
22
+ */
23
+ async signAuthorization() {
24
+ const authorization = await this.walletClient.signAuthorization({
25
+ contractAddress: this.delegateContract,
26
+ account: this.walletClient.account,
27
+ chainId: 0, // 0 means valid on any EIP-7702 compatible chain
28
+ });
29
+ return authorization;
30
+ }
31
+ /**
32
+ * Submit signed EIP-7702 authorization transaction(s)
33
+ * Supports authorizing multiple EOAs in a single transaction
34
+ * Call this with a paymaster client to broadcast the authorization transaction
35
+ * The paymaster pays for the gas
36
+ */
37
+ async submitAuthorizations(authorizations) {
38
+ if (authorizations.length === 0) {
39
+ throw new Error("Authorization list cannot be empty");
40
+ }
41
+ const authTxHash = await this.walletClient.sendTransaction({
42
+ from: "0x0000000000000000000000000000000000000000",
43
+ authorizationList: authorizations,
44
+ to: "0x0000000000000000000000000000000000000000",
45
+ type: "eip7702",
46
+ account: this.walletClient.account,
47
+ });
48
+ const receipt = await this.publicClient.waitForTransactionReceipt({
49
+ hash: authTxHash,
50
+ });
51
+ if (receipt.status !== "success") {
52
+ // Try to get the revert reason if available
53
+ const revertReason = await this.getRevertReason(authTxHash);
54
+ throw new Error(`Authorization failed: ${revertReason || "Transaction reverted"}. ` +
55
+ `Gas used: ${receipt.gasUsed}/${receipt.cumulativeGasUsed}. ` +
56
+ `Transaction hash: ${authTxHash}`);
57
+ }
58
+ return { txHash: authTxHash, blockNumber: receipt.blockNumber };
59
+ }
60
+ /**
61
+ * Check if an EOA is delegated to the gas station contract
62
+ * If no address is provided, uses the signer's address
63
+ */
64
+ async isAuthorized(eoaAddress) {
65
+ const address = eoaAddress ?? this.walletClient.account.address;
66
+ const isAuthorized = await this.publicClient.readContract({
67
+ address: this.executionContract,
68
+ abi: gasStation.gasStationAbi,
69
+ functionName: "isDelegated",
70
+ args: [address],
71
+ });
72
+ return isAuthorized;
73
+ }
74
+ /**
75
+ * Get the current nonce for an EOA address from the gas station contract
76
+ * If no address is provided, uses the signer's address
77
+ */
78
+ async getNonce(eoaAddress) {
79
+ const address = eoaAddress ?? this.walletClient.account.address;
80
+ const nonce = await this.publicClient.readContract({
81
+ address: this.executionContract,
82
+ abi: gasStation.gasStationAbi,
83
+ functionName: "getNonce",
84
+ args: [address],
85
+ });
86
+ return nonce;
87
+ }
88
+ /**
89
+ * Attempts to get the revert reason from a failed transaction.
90
+ * Replays the transaction via eth_call to extract detailed error information.
91
+ *
92
+ * This helps surface on-chain failure reasons such as:
93
+ * - Out of gas errors
94
+ * - Revert with reason strings
95
+ * - Custom error selectors
96
+ * - Insufficient balance errors
97
+ */
98
+ async getRevertReason(txHash) {
99
+ try {
100
+ const tx = await this.publicClient.getTransaction({ hash: txHash });
101
+ // Replay the transaction via eth_call to trigger the revert and get the reason
102
+ await this.publicClient.call({
103
+ to: tx.to,
104
+ data: tx.input,
105
+ gas: tx.gas,
106
+ value: tx.value,
107
+ });
108
+ // If call succeeds, we don't have a revert reason (shouldn't happen for failed tx)
109
+ return null;
110
+ }
111
+ catch (error) {
112
+ // Extract revert reason from error message
113
+ if (error?.details) {
114
+ return error.details;
115
+ }
116
+ if (error?.message) {
117
+ // Check for out of gas errors
118
+ const outOfGasMatch = error.message.match(/out of gas/i);
119
+ if (outOfGasMatch) {
120
+ return "Out of gas";
121
+ }
122
+ // Check for standard revert with reason string
123
+ const revertMatch = error.message.match(/reverted with reason string '([^']+)'/);
124
+ if (revertMatch) {
125
+ return revertMatch[1];
126
+ }
127
+ // Check for custom errors (Solidity 0.8.4+)
128
+ const customErrorMatch = error.message.match(/reverted with the following \(custom\) error:\s*([^\n]+)/);
129
+ if (customErrorMatch) {
130
+ return customErrorMatch[1];
131
+ }
132
+ // Return the full error message if no specific pattern matches
133
+ return error.message;
134
+ }
135
+ return null;
136
+ }
137
+ }
138
+ /**
139
+ * Create an intent builder for composing complex transactions
140
+ * Call this with an end-user client to create intents for signing
141
+ */
142
+ createIntent() {
143
+ if (!this.walletClient.account?.address) {
144
+ throw new Error(`Wallet client account is not properly configured. Account: ${JSON.stringify(this.walletClient.account)}`);
145
+ }
146
+ return intentBuilder.IntentBuilder.create({
147
+ eoaWalletClient: this.walletClient,
148
+ chainId: this.walletClient.chain.id,
149
+ eoaAddress: this.walletClient.account.address,
150
+ });
151
+ }
152
+ /**
153
+ * Sign an execution transaction for a signed intent (paymaster signs, doesn't send)
154
+ * This is useful for testing policies - the paymaster attempts to sign the execution
155
+ * but doesn't actually broadcast it to the network.
156
+ * Call this with a paymaster client to test if the paymaster can sign the execution.
157
+ */
158
+ async signExecution(intent) {
159
+ // Pack the execution data (signature, nonce, deadline, args)
160
+ const packedData = gasStationUtils.packExecutionData({
161
+ signature: intent.signature,
162
+ nonce: intent.nonce,
163
+ deadline: intent.deadline,
164
+ args: intent.callData,
165
+ });
166
+ // Encode the function call data
167
+ const callData = viem.encodeFunctionData({
168
+ abi: gasStation.gasStationAbi,
169
+ functionName: "execute",
170
+ args: [
171
+ intent.eoaAddress,
172
+ intent.outputContract,
173
+ intent.ethAmount,
174
+ packedData,
175
+ ],
176
+ });
177
+ // Sign the transaction without sending it
178
+ const signedTx = await this.walletClient.signTransaction({
179
+ to: this.executionContract,
180
+ data: callData,
181
+ gas: BigInt(200000),
182
+ type: "eip1559",
183
+ account: this.walletClient.account,
184
+ chain: this.walletClient.chain,
185
+ });
186
+ return signedTx;
187
+ }
188
+ /**
189
+ * Execute a signed intent through the gas station contract.
190
+ * Packs the execution data according to the delegate contract's expected format and
191
+ * submits it via the execution contract.
192
+ * Call this with a paymaster client to submit and pay for the transaction.
193
+ */
194
+ async execute(intent) {
195
+ // Pack the execution data (signature, nonce, deadline, args)
196
+ const packedData = gasStationUtils.packExecutionData({
197
+ signature: intent.signature,
198
+ nonce: intent.nonce,
199
+ deadline: intent.deadline,
200
+ args: intent.callData,
201
+ });
202
+ // Call the unified execute function with explicit parameters
203
+ const txHash = await this.walletClient.sendTransaction({
204
+ to: this.executionContract,
205
+ data: viem.encodeFunctionData({
206
+ abi: gasStation.gasStationAbi,
207
+ functionName: "execute",
208
+ args: [
209
+ intent.eoaAddress,
210
+ intent.outputContract,
211
+ intent.ethAmount,
212
+ packedData,
213
+ ],
214
+ }),
215
+ gas: BigInt(200000),
216
+ account: this.walletClient.account,
217
+ });
218
+ const receipt = await this.publicClient.waitForTransactionReceipt({
219
+ hash: txHash,
220
+ });
221
+ if (receipt.status !== "success") {
222
+ // Try to get the revert reason if available
223
+ const revertReason = await this.getRevertReason(txHash);
224
+ throw new Error(`Execution failed: ${revertReason || "Transaction reverted"}. ` +
225
+ `Gas used: ${receipt.gasUsed}/${receipt.cumulativeGasUsed}. ` +
226
+ `Transaction hash: ${txHash}`);
227
+ }
228
+ return {
229
+ txHash,
230
+ blockNumber: receipt.blockNumber,
231
+ gasUsed: receipt.gasUsed,
232
+ };
233
+ }
234
+ }
235
+
236
+ exports.GasStationClient = GasStationClient;
237
+ //# sourceMappingURL=gasStationClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gasStationClient.js","sources":["../src/gasStationClient.ts"],"sourcesContent":[null],"names":["config","createPublicClientForChain","DEFAULT_DELEGATE_CONTRACT","DEFAULT_EXECUTION_CONTRACT","gasStationAbi","IntentBuilder","packExecutionData","encodeFunctionData"],"mappings":"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"}
@@ -0,0 +1,235 @@
1
+ import { encodeFunctionData } from 'viem';
2
+ import { gasStationAbi } from './abi/gas-station.mjs';
3
+ import { DEFAULT_DELEGATE_CONTRACT, DEFAULT_EXECUTION_CONTRACT } from './config.mjs';
4
+ import { IntentBuilder } from './intentBuilder.mjs';
5
+ import { createPublicClientForChain, packExecutionData } from './gasStationUtils.mjs';
6
+
7
+ class GasStationClient {
8
+ constructor(config) {
9
+ this.walletClient = config.walletClient;
10
+ this.publicClient = createPublicClientForChain(config.walletClient.chain, config.walletClient.transport.url);
11
+ this.delegateContract =
12
+ config.delegateContract ?? DEFAULT_DELEGATE_CONTRACT;
13
+ this.executionContract =
14
+ config.executionContract ?? DEFAULT_EXECUTION_CONTRACT;
15
+ }
16
+ /**
17
+ * Sign an EIP-7702 authorization to delegate control to the gas station contract
18
+ * Call this with an end-user client to get a signed authorization
19
+ * The authorization can then be submitted by the paymaster using submitAuthorization()
20
+ */
21
+ async signAuthorization() {
22
+ const authorization = await this.walletClient.signAuthorization({
23
+ contractAddress: this.delegateContract,
24
+ account: this.walletClient.account,
25
+ chainId: 0, // 0 means valid on any EIP-7702 compatible chain
26
+ });
27
+ return authorization;
28
+ }
29
+ /**
30
+ * Submit signed EIP-7702 authorization transaction(s)
31
+ * Supports authorizing multiple EOAs in a single transaction
32
+ * Call this with a paymaster client to broadcast the authorization transaction
33
+ * The paymaster pays for the gas
34
+ */
35
+ async submitAuthorizations(authorizations) {
36
+ if (authorizations.length === 0) {
37
+ throw new Error("Authorization list cannot be empty");
38
+ }
39
+ const authTxHash = await this.walletClient.sendTransaction({
40
+ from: "0x0000000000000000000000000000000000000000",
41
+ authorizationList: authorizations,
42
+ to: "0x0000000000000000000000000000000000000000",
43
+ type: "eip7702",
44
+ account: this.walletClient.account,
45
+ });
46
+ const receipt = await this.publicClient.waitForTransactionReceipt({
47
+ hash: authTxHash,
48
+ });
49
+ if (receipt.status !== "success") {
50
+ // Try to get the revert reason if available
51
+ const revertReason = await this.getRevertReason(authTxHash);
52
+ throw new Error(`Authorization failed: ${revertReason || "Transaction reverted"}. ` +
53
+ `Gas used: ${receipt.gasUsed}/${receipt.cumulativeGasUsed}. ` +
54
+ `Transaction hash: ${authTxHash}`);
55
+ }
56
+ return { txHash: authTxHash, blockNumber: receipt.blockNumber };
57
+ }
58
+ /**
59
+ * Check if an EOA is delegated to the gas station contract
60
+ * If no address is provided, uses the signer's address
61
+ */
62
+ async isAuthorized(eoaAddress) {
63
+ const address = eoaAddress ?? this.walletClient.account.address;
64
+ const isAuthorized = await this.publicClient.readContract({
65
+ address: this.executionContract,
66
+ abi: gasStationAbi,
67
+ functionName: "isDelegated",
68
+ args: [address],
69
+ });
70
+ return isAuthorized;
71
+ }
72
+ /**
73
+ * Get the current nonce for an EOA address from the gas station contract
74
+ * If no address is provided, uses the signer's address
75
+ */
76
+ async getNonce(eoaAddress) {
77
+ const address = eoaAddress ?? this.walletClient.account.address;
78
+ const nonce = await this.publicClient.readContract({
79
+ address: this.executionContract,
80
+ abi: gasStationAbi,
81
+ functionName: "getNonce",
82
+ args: [address],
83
+ });
84
+ return nonce;
85
+ }
86
+ /**
87
+ * Attempts to get the revert reason from a failed transaction.
88
+ * Replays the transaction via eth_call to extract detailed error information.
89
+ *
90
+ * This helps surface on-chain failure reasons such as:
91
+ * - Out of gas errors
92
+ * - Revert with reason strings
93
+ * - Custom error selectors
94
+ * - Insufficient balance errors
95
+ */
96
+ async getRevertReason(txHash) {
97
+ try {
98
+ const tx = await this.publicClient.getTransaction({ hash: txHash });
99
+ // Replay the transaction via eth_call to trigger the revert and get the reason
100
+ await this.publicClient.call({
101
+ to: tx.to,
102
+ data: tx.input,
103
+ gas: tx.gas,
104
+ value: tx.value,
105
+ });
106
+ // If call succeeds, we don't have a revert reason (shouldn't happen for failed tx)
107
+ return null;
108
+ }
109
+ catch (error) {
110
+ // Extract revert reason from error message
111
+ if (error?.details) {
112
+ return error.details;
113
+ }
114
+ if (error?.message) {
115
+ // Check for out of gas errors
116
+ const outOfGasMatch = error.message.match(/out of gas/i);
117
+ if (outOfGasMatch) {
118
+ return "Out of gas";
119
+ }
120
+ // Check for standard revert with reason string
121
+ const revertMatch = error.message.match(/reverted with reason string '([^']+)'/);
122
+ if (revertMatch) {
123
+ return revertMatch[1];
124
+ }
125
+ // Check for custom errors (Solidity 0.8.4+)
126
+ const customErrorMatch = error.message.match(/reverted with the following \(custom\) error:\s*([^\n]+)/);
127
+ if (customErrorMatch) {
128
+ return customErrorMatch[1];
129
+ }
130
+ // Return the full error message if no specific pattern matches
131
+ return error.message;
132
+ }
133
+ return null;
134
+ }
135
+ }
136
+ /**
137
+ * Create an intent builder for composing complex transactions
138
+ * Call this with an end-user client to create intents for signing
139
+ */
140
+ createIntent() {
141
+ if (!this.walletClient.account?.address) {
142
+ throw new Error(`Wallet client account is not properly configured. Account: ${JSON.stringify(this.walletClient.account)}`);
143
+ }
144
+ return IntentBuilder.create({
145
+ eoaWalletClient: this.walletClient,
146
+ chainId: this.walletClient.chain.id,
147
+ eoaAddress: this.walletClient.account.address,
148
+ });
149
+ }
150
+ /**
151
+ * Sign an execution transaction for a signed intent (paymaster signs, doesn't send)
152
+ * This is useful for testing policies - the paymaster attempts to sign the execution
153
+ * but doesn't actually broadcast it to the network.
154
+ * Call this with a paymaster client to test if the paymaster can sign the execution.
155
+ */
156
+ async signExecution(intent) {
157
+ // Pack the execution data (signature, nonce, deadline, args)
158
+ const packedData = packExecutionData({
159
+ signature: intent.signature,
160
+ nonce: intent.nonce,
161
+ deadline: intent.deadline,
162
+ args: intent.callData,
163
+ });
164
+ // Encode the function call data
165
+ const callData = encodeFunctionData({
166
+ abi: gasStationAbi,
167
+ functionName: "execute",
168
+ args: [
169
+ intent.eoaAddress,
170
+ intent.outputContract,
171
+ intent.ethAmount,
172
+ packedData,
173
+ ],
174
+ });
175
+ // Sign the transaction without sending it
176
+ const signedTx = await this.walletClient.signTransaction({
177
+ to: this.executionContract,
178
+ data: callData,
179
+ gas: BigInt(200000),
180
+ type: "eip1559",
181
+ account: this.walletClient.account,
182
+ chain: this.walletClient.chain,
183
+ });
184
+ return signedTx;
185
+ }
186
+ /**
187
+ * Execute a signed intent through the gas station contract.
188
+ * Packs the execution data according to the delegate contract's expected format and
189
+ * submits it via the execution contract.
190
+ * Call this with a paymaster client to submit and pay for the transaction.
191
+ */
192
+ async execute(intent) {
193
+ // Pack the execution data (signature, nonce, deadline, args)
194
+ const packedData = packExecutionData({
195
+ signature: intent.signature,
196
+ nonce: intent.nonce,
197
+ deadline: intent.deadline,
198
+ args: intent.callData,
199
+ });
200
+ // Call the unified execute function with explicit parameters
201
+ const txHash = await this.walletClient.sendTransaction({
202
+ to: this.executionContract,
203
+ data: encodeFunctionData({
204
+ abi: gasStationAbi,
205
+ functionName: "execute",
206
+ args: [
207
+ intent.eoaAddress,
208
+ intent.outputContract,
209
+ intent.ethAmount,
210
+ packedData,
211
+ ],
212
+ }),
213
+ gas: BigInt(200000),
214
+ account: this.walletClient.account,
215
+ });
216
+ const receipt = await this.publicClient.waitForTransactionReceipt({
217
+ hash: txHash,
218
+ });
219
+ if (receipt.status !== "success") {
220
+ // Try to get the revert reason if available
221
+ const revertReason = await this.getRevertReason(txHash);
222
+ throw new Error(`Execution failed: ${revertReason || "Transaction reverted"}. ` +
223
+ `Gas used: ${receipt.gasUsed}/${receipt.cumulativeGasUsed}. ` +
224
+ `Transaction hash: ${txHash}`);
225
+ }
226
+ return {
227
+ txHash,
228
+ blockNumber: receipt.blockNumber,
229
+ gasUsed: receipt.gasUsed,
230
+ };
231
+ }
232
+ }
233
+
234
+ export { GasStationClient };
235
+ //# sourceMappingURL=gasStationClient.mjs.map