@0xkey-io/gas-station 0.1.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/LICENSE +201 -0
- package/README.md +655 -0
- package/dist/abi/gas-station.d.ts +500 -0
- package/dist/abi/gas-station.d.ts.map +1 -0
- package/dist/abi/gas-station.js +252 -0
- package/dist/abi/gas-station.js.map +1 -0
- package/dist/abi/gas-station.mjs +250 -0
- package/dist/abi/gas-station.mjs.map +1 -0
- package/dist/abi/reimbursable-gas-station.d.ts +756 -0
- package/dist/abi/reimbursable-gas-station.d.ts.map +1 -0
- package/dist/abi/reimbursable-gas-station.js +625 -0
- package/dist/abi/reimbursable-gas-station.js.map +1 -0
- package/dist/abi/reimbursable-gas-station.mjs +623 -0
- package/dist/abi/reimbursable-gas-station.mjs.map +1 -0
- package/dist/config.d.ts +57 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +59 -0
- package/dist/config.js.map +1 -0
- package/dist/config.mjs +52 -0
- package/dist/config.mjs.map +1 -0
- package/dist/gasStationClient.d.ts +110 -0
- package/dist/gasStationClient.d.ts.map +1 -0
- package/dist/gasStationClient.js +415 -0
- package/dist/gasStationClient.js.map +1 -0
- package/dist/gasStationClient.mjs +413 -0
- package/dist/gasStationClient.mjs.map +1 -0
- package/dist/gasStationUtils.d.ts +7250 -0
- package/dist/gasStationUtils.d.ts.map +1 -0
- package/dist/gasStationUtils.js +147 -0
- package/dist/gasStationUtils.js.map +1 -0
- package/dist/gasStationUtils.mjs +137 -0
- package/dist/gasStationUtils.mjs.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +8 -0
- package/dist/index.mjs.map +1 -0
- package/dist/intentBuilder.d.ts +75 -0
- package/dist/intentBuilder.d.ts.map +1 -0
- package/dist/intentBuilder.js +259 -0
- package/dist/intentBuilder.js.map +1 -0
- package/dist/intentBuilder.mjs +257 -0
- package/dist/intentBuilder.mjs.map +1 -0
- package/dist/policyUtils.d.ts +271 -0
- package/dist/policyUtils.d.ts.map +1 -0
- package/dist/policyUtils.js +386 -0
- package/dist/policyUtils.js.map +1 -0
- package/dist/policyUtils.mjs +380 -0
- package/dist/policyUtils.mjs.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
import { gasStationAbi } from './abi/gas-station.mjs';
|
|
2
|
+
|
|
3
|
+
// Policy utilities for ZeroXKey gas station restrictions
|
|
4
|
+
/**
|
|
5
|
+
* Build a ZeroXKey policy to restrict what EIP-712 intents an EOA can sign
|
|
6
|
+
* This protects at the signing layer - EOA cannot create signatures outside policy
|
|
7
|
+
*
|
|
8
|
+
* @param config - Policy configuration
|
|
9
|
+
* @param config.organizationId - ZeroXKey organization ID
|
|
10
|
+
* @param config.eoaUserId - ZeroXKey user ID for the EOA (primary approver)
|
|
11
|
+
* @param config.additionalApprovers - Optional additional user IDs that must also approve (creates AND condition)
|
|
12
|
+
* @param config.customConsensus - Optional custom consensus expression (overrides eoaUserId and additionalApprovers)
|
|
13
|
+
* @param config.restrictions - Signing restrictions
|
|
14
|
+
* @param config.restrictions.allowedContracts - Whitelist of contract addresses EOA can sign intents for
|
|
15
|
+
* @param config.restrictions.disallowEthTransfer - Whether to disallow ETH transfers (if true, value must be 0)
|
|
16
|
+
* @param config.policyName - Optional policy name
|
|
17
|
+
* @returns Policy object ready to submit to ZeroXKey createPolicy API
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // Simple: single user approval, token-only transfers
|
|
21
|
+
* const policy = buildIntentSigningPolicy({
|
|
22
|
+
* organizationId: "a5b89e4f-1234-5678-9abc-def012345678",
|
|
23
|
+
* eoaUserId: "3c7d6e8a-4b5c-6d7e-8f9a-0b1c2d3e4f5a",
|
|
24
|
+
* restrictions: {
|
|
25
|
+
* allowedContracts: ["0x833...USDC", "0x6B1...DAI"],
|
|
26
|
+
* disallowEthTransfer: true,
|
|
27
|
+
* },
|
|
28
|
+
* policyName: "Stablecoin Only",
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // Resulting policy:
|
|
32
|
+
* {
|
|
33
|
+
* organizationId: "a5b89e4f-1234-5678-9abc-def012345678",
|
|
34
|
+
* policyName: "Stablecoin Only",
|
|
35
|
+
* effect: "EFFECT_ALLOW",
|
|
36
|
+
* consensus: "approvers.any(user, user.id == '3c7d6e8a-4b5c-6d7e-8f9a-0b1c2d3e4f5a')",
|
|
37
|
+
* condition: "activity.resource == 'PRIVATE_KEY' && activity.action == 'SIGN' && " +
|
|
38
|
+
* "eth.eip_712.primary_type == 'Execution' && " +
|
|
39
|
+
* "(eth.eip_712.message['to'] == '0x833...usdc' || " +
|
|
40
|
+
* "eth.eip_712.message['to'] == '0x6b1...dai') && " +
|
|
41
|
+
* "eth.eip_712.message['value'] == '0'",
|
|
42
|
+
* notes: "Restricts which EIP-712 intents the EOA can sign for gas station execution"
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* // Multi-approval: EOA AND backup user must both approve
|
|
47
|
+
* const policy = buildIntentSigningPolicy({
|
|
48
|
+
* organizationId: "a5b89e4f-1234-5678-9abc-def012345678",
|
|
49
|
+
* eoaUserId: "3c7d6e8a-4b5c-6d7e-8f9a-0b1c2d3e4f5a",
|
|
50
|
+
* additionalApprovers: ["9d4e2f5b-6c7d-8e9f-0a1b-2c3d4e5f6a7b"],
|
|
51
|
+
* restrictions: {
|
|
52
|
+
* allowedContracts: ["0x833...USDC"],
|
|
53
|
+
* disallowEthTransfer: true,
|
|
54
|
+
* },
|
|
55
|
+
* });
|
|
56
|
+
*
|
|
57
|
+
* // Resulting policy:
|
|
58
|
+
* {
|
|
59
|
+
* organizationId: "a5b89e4f-1234-5678-9abc-def012345678",
|
|
60
|
+
* policyName: "Gas Station Intent Signing Policy",
|
|
61
|
+
* effect: "EFFECT_ALLOW",
|
|
62
|
+
* consensus: "approvers.any(user, user.id == '3c7d6e8a-4b5c-6d7e-8f9a-0b1c2d3e4f5a') && " +
|
|
63
|
+
* "approvers.any(user, user.id == '9d4e2f5b-6c7d-8e9f-0a1b-2c3d4e5f6a7b')",
|
|
64
|
+
* condition: "activity.resource == 'PRIVATE_KEY' && activity.action == 'SIGN' && " +
|
|
65
|
+
* "eth.eip_712.primary_type == 'Execution' && " +
|
|
66
|
+
* "(eth.eip_712.message['to'] == '0x833...usdc') && " +
|
|
67
|
+
* "eth.eip_712.message['value'] == '0'",
|
|
68
|
+
* notes: "Restricts which EIP-712 intents the EOA can sign for gas station execution"
|
|
69
|
+
* }
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* // Advanced: custom consensus expression
|
|
73
|
+
* const policy = buildIntentSigningPolicy({
|
|
74
|
+
* organizationId: "a5b89e4f-1234-5678-9abc-def012345678",
|
|
75
|
+
* eoaUserId: "3c7d6e8a-4b5c-6d7e-8f9a-0b1c2d3e4f5a",
|
|
76
|
+
* customConsensus: "approvers.count() >= 2",
|
|
77
|
+
* restrictions: {
|
|
78
|
+
* disallowEthTransfer: false,
|
|
79
|
+
* },
|
|
80
|
+
* });
|
|
81
|
+
*
|
|
82
|
+
* await 0xkeyClient.apiClient().createPolicy(policy);
|
|
83
|
+
*/
|
|
84
|
+
function buildIntentSigningPolicy(config) {
|
|
85
|
+
const conditions = [
|
|
86
|
+
"activity.resource == 'PRIVATE_KEY'",
|
|
87
|
+
"activity.action == 'SIGN'",
|
|
88
|
+
"eth.eip_712.primary_type == 'Execution'",
|
|
89
|
+
];
|
|
90
|
+
if (config.restrictions?.allowedContracts &&
|
|
91
|
+
config.restrictions.allowedContracts.length > 0) {
|
|
92
|
+
// Build OR conditions for each allowed contract
|
|
93
|
+
// Convert to lowercase for case-insensitive comparison
|
|
94
|
+
const contractConditions = config.restrictions.allowedContracts
|
|
95
|
+
.map((c) => `eth.eip_712.message['to'] == '${c.toLowerCase()}'`)
|
|
96
|
+
.join(" || ");
|
|
97
|
+
conditions.push(`(${contractConditions})`);
|
|
98
|
+
}
|
|
99
|
+
if (!!config.restrictions?.disallowEthTransfer) {
|
|
100
|
+
conditions.push(`eth.eip_712.message['value'] == '0'`);
|
|
101
|
+
}
|
|
102
|
+
// Build consensus expression
|
|
103
|
+
let consensus;
|
|
104
|
+
if (config.customConsensus) {
|
|
105
|
+
// Use custom consensus if provided
|
|
106
|
+
consensus = config.customConsensus;
|
|
107
|
+
}
|
|
108
|
+
else if (config.additionalApprovers &&
|
|
109
|
+
config.additionalApprovers.length > 0) {
|
|
110
|
+
// Build multi-user AND condition: eoaUserId AND all additionalApprovers must approve
|
|
111
|
+
const approverConditions = [
|
|
112
|
+
`approvers.any(user, user.id == '${config.eoaUserId}')`,
|
|
113
|
+
...config.additionalApprovers.map((id) => `approvers.any(user, user.id == '${id}')`),
|
|
114
|
+
];
|
|
115
|
+
consensus = approverConditions.join(" && ");
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
// Default: only eoaUserId can approve
|
|
119
|
+
consensus = `approvers.any(user, user.id == '${config.eoaUserId}')`;
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
organizationId: config.organizationId,
|
|
123
|
+
policyName: config.policyName || "Gas Station Intent Signing Policy",
|
|
124
|
+
effect: "EFFECT_ALLOW",
|
|
125
|
+
consensus,
|
|
126
|
+
condition: conditions.join(" && "),
|
|
127
|
+
notes: "Restricts which EIP-712 intents the EOA can sign for gas station execution",
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Build a ZeroXKey policy to restrict what the paymaster can execute on-chain.
|
|
132
|
+
* This protects at the execution layer - paymaster cannot submit transactions outside policy.
|
|
133
|
+
*
|
|
134
|
+
* This function uses ZeroXKey's Smart Contract Interface feature to parse the
|
|
135
|
+
* execute(address _targetEoA, address _to, uint256 ethAmount, bytes _data) ABI.
|
|
136
|
+
* Before using this function, ensure the Gas Station ABI is uploaded via
|
|
137
|
+
* ensureGasStationInterface() - this is typically handled automatically.
|
|
138
|
+
*
|
|
139
|
+
* @param config - Policy configuration
|
|
140
|
+
* @param config.organizationId - ZeroXKey organization ID
|
|
141
|
+
* @param config.paymasterUserId - ZeroXKey user ID for the paymaster (primary approver)
|
|
142
|
+
* @param config.additionalApprovers - Optional additional user IDs that can approve (creates OR condition)
|
|
143
|
+
* @param config.customConsensus - Optional custom consensus expression (overrides paymasterUserId and additionalApprovers)
|
|
144
|
+
* @param config.executionContractAddress - Gas station execution contract address
|
|
145
|
+
* @param config.restrictions - Execution restrictions
|
|
146
|
+
* @param config.restrictions.allowedEOAs - Whitelist of EOA addresses paymaster can execute for
|
|
147
|
+
* @param config.restrictions.allowedContracts - Whitelist of output contract addresses (target contracts)
|
|
148
|
+
* @param config.restrictions.maxEthAmount - Maximum ETH amount in wei that can be transferred
|
|
149
|
+
* @param config.restrictions.maxGasPrice - Maximum gas price in wei
|
|
150
|
+
* @param config.restrictions.maxGasLimit - Maximum gas limit
|
|
151
|
+
* @param config.policyName - Optional policy name
|
|
152
|
+
* @returns Policy object ready to submit to ZeroXKey createPolicy API
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* // Simple: single paymaster approval with ETH amount limit
|
|
156
|
+
* const policy = buildPaymasterExecutionPolicy({
|
|
157
|
+
* organizationId: "f8c3a5e7-9876-5432-1abc-def098765432",
|
|
158
|
+
* paymasterUserId: "8f2a1b4c-5d6e-7f8a-9b0c-1d2e3f4a5b6c",
|
|
159
|
+
* executionContractAddress: "0x00000000008c57a1CE37836a5e9d36759D070d8c",
|
|
160
|
+
* restrictions: {
|
|
161
|
+
* allowedEOAs: ["0xAli...ce", "0xBob...by"],
|
|
162
|
+
* allowedContracts: ["0x833...USDC", "0x6B1...DAI"],
|
|
163
|
+
* maxEthAmount: parseEther("0.1"), // Max 0.1 ETH per transaction
|
|
164
|
+
* maxGasPrice: parseGwei("50"),
|
|
165
|
+
* maxGasLimit: 500000n,
|
|
166
|
+
* },
|
|
167
|
+
* policyName: "Paymaster Protection",
|
|
168
|
+
* });
|
|
169
|
+
*
|
|
170
|
+
* // Resulting policy (uses ABI parsing):
|
|
171
|
+
* {
|
|
172
|
+
* organizationId: "f8c3a5e7-9876-5432-1abc-def098765432",
|
|
173
|
+
* policyName: "Paymaster Protection",
|
|
174
|
+
* effect: "EFFECT_ALLOW",
|
|
175
|
+
* consensus: "approvers.any(user, user.id == '8f2a1b4c-5d6e-7f8a-9b0c-1d2e3f4a5b6c')",
|
|
176
|
+
* condition: "activity.resource == 'PRIVATE_KEY' && activity.action == 'SIGN' && " +
|
|
177
|
+
* "eth.tx.to == '0x00000000008c57a1ce37836a5e9d36759d070d8c' && " +
|
|
178
|
+
* "(eth.tx.contract_call_args['_to'] == '0x833...usdc' || " +
|
|
179
|
+
* "eth.tx.contract_call_args['_to'] == '0x6b1...dai') && " +
|
|
180
|
+
* "(eth.tx.contract_call_args['_target'] == '0xali...ce' || " +
|
|
181
|
+
* "eth.tx.contract_call_args['_target'] == '0xbob...by') && " +
|
|
182
|
+
* "eth.tx.contract_call_args['_ethAmount'] <= 100000000000000000 && " +
|
|
183
|
+
* "eth.tx.gasPrice <= 50000000000 && eth.tx.gas <= 500000",
|
|
184
|
+
* notes: "Restricts which execute() transactions the paymaster can submit on-chain"
|
|
185
|
+
* }
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* // Multi-user: primary paymaster OR backup can approve
|
|
189
|
+
* const policy = buildPaymasterExecutionPolicy({
|
|
190
|
+
* organizationId: "f8c3a5e7-9876-5432-1abc-def098765432",
|
|
191
|
+
* paymasterUserId: "8f2a1b4c-5d6e-7f8a-9b0c-1d2e3f4a5b6c",
|
|
192
|
+
* additionalApprovers: ["2e4f6a8b-9c0d-1e2f-3a4b-5c6d7e8f9a0b"],
|
|
193
|
+
* executionContractAddress: "0x00000000008c57a1CE37836a5e9d36759D070d8c",
|
|
194
|
+
* restrictions: {
|
|
195
|
+
* allowedEOAs: ["0xAli...ce"],
|
|
196
|
+
* maxEthAmount: parseEther("1"), // Max 1 ETH
|
|
197
|
+
* maxGasPrice: parseGwei("100"),
|
|
198
|
+
* },
|
|
199
|
+
* });
|
|
200
|
+
*
|
|
201
|
+
* // Resulting policy (uses ABI parsing):
|
|
202
|
+
* {
|
|
203
|
+
* organizationId: "f8c3a5e7-9876-5432-1abc-def098765432",
|
|
204
|
+
* policyName: "Gas Station Paymaster Execution Policy",
|
|
205
|
+
* effect: "EFFECT_ALLOW",
|
|
206
|
+
* consensus: "approvers.any(user, user.id == '8f2a1b4c-5d6e-7f8a-9b0c-1d2e3f4a5b6c' || " +
|
|
207
|
+
* "user.id == '2e4f6a8b-9c0d-1e2f-3a4b-5c6d7e8f9a0b')",
|
|
208
|
+
* condition: "activity.resource == 'PRIVATE_KEY' && activity.action == 'SIGN' && " +
|
|
209
|
+
* "eth.tx.to == '0x00000000008c57a1ce37836a5e9d36759d070d8c' && " +
|
|
210
|
+
* "(eth.tx.contract_call_args['_target'] == '0xali...ce') && " +
|
|
211
|
+
* "eth.tx.contract_call_args['_ethAmount'] <= 1000000000000000000 && " +
|
|
212
|
+
* "eth.tx.gasPrice <= 100000000000",
|
|
213
|
+
* notes: "Restricts which execute() transactions the paymaster can submit on-chain"
|
|
214
|
+
* }
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* // Advanced: require multiple approvals
|
|
218
|
+
* const policy = buildPaymasterExecutionPolicy({
|
|
219
|
+
* organizationId: "f8c3a5e7-9876-5432-1abc-def098765432",
|
|
220
|
+
* paymasterUserId: "8f2a1b4c-5d6e-7f8a-9b0c-1d2e3f4a5b6c",
|
|
221
|
+
* customConsensus: "approvers.count() >= 2",
|
|
222
|
+
* executionContractAddress: "0x00000000008c57a1CE37836a5e9d36759D070d8c",
|
|
223
|
+
* restrictions: { ... },
|
|
224
|
+
* });
|
|
225
|
+
*
|
|
226
|
+
* await 0xkeyClient.apiClient().createPolicy(policy);
|
|
227
|
+
*/
|
|
228
|
+
function buildPaymasterExecutionPolicy(config) {
|
|
229
|
+
const conditions = [
|
|
230
|
+
"activity.resource == 'PRIVATE_KEY'",
|
|
231
|
+
"activity.action == 'SIGN'",
|
|
232
|
+
`eth.tx.to == '${config.executionContractAddress.toLowerCase()}'`,
|
|
233
|
+
];
|
|
234
|
+
// Check output contract address using ABI parsing
|
|
235
|
+
// ZeroXKey parses execute(address _target, address _to, uint256 _ethAmount, bytes _data)
|
|
236
|
+
// and exposes arguments via eth.tx.contract_call_args
|
|
237
|
+
if (config.restrictions?.allowedContracts &&
|
|
238
|
+
config.restrictions.allowedContracts.length > 0) {
|
|
239
|
+
const contracts = config.restrictions.allowedContracts
|
|
240
|
+
.map((addr) => {
|
|
241
|
+
const cleanAddr = addr.toLowerCase();
|
|
242
|
+
return `eth.tx.contract_call_args['_to'] == '${cleanAddr}'`;
|
|
243
|
+
})
|
|
244
|
+
.join(" || ");
|
|
245
|
+
conditions.push(`(${contracts})`);
|
|
246
|
+
}
|
|
247
|
+
// Check EOA address using ABI parsing
|
|
248
|
+
if (config.restrictions?.allowedEOAs &&
|
|
249
|
+
config.restrictions.allowedEOAs.length > 0) {
|
|
250
|
+
const eoas = config.restrictions.allowedEOAs
|
|
251
|
+
.map((addr) => {
|
|
252
|
+
const cleanAddr = addr.toLowerCase();
|
|
253
|
+
return `eth.tx.contract_call_args['_target'] == '${cleanAddr}'`;
|
|
254
|
+
})
|
|
255
|
+
.join(" || ");
|
|
256
|
+
conditions.push(`(${eoas})`);
|
|
257
|
+
}
|
|
258
|
+
// Check ETH amount using ABI parsing (direct uint256 comparison)
|
|
259
|
+
if (config.restrictions?.maxEthAmount !== undefined) {
|
|
260
|
+
conditions.push(`eth.tx.contract_call_args['_ethAmount'] <= ${config.restrictions.maxEthAmount}`);
|
|
261
|
+
}
|
|
262
|
+
if (config.restrictions?.maxGasPrice !== undefined) {
|
|
263
|
+
conditions.push(`eth.tx.gasPrice <= ${config.restrictions.maxGasPrice}`);
|
|
264
|
+
}
|
|
265
|
+
if (config.restrictions?.maxGasLimit !== undefined) {
|
|
266
|
+
conditions.push(`eth.tx.gas <= ${config.restrictions.maxGasLimit}`);
|
|
267
|
+
}
|
|
268
|
+
// Build consensus expression
|
|
269
|
+
let consensus;
|
|
270
|
+
if (config.customConsensus) {
|
|
271
|
+
// Use custom consensus if provided
|
|
272
|
+
consensus = config.customConsensus;
|
|
273
|
+
}
|
|
274
|
+
else if (config.additionalApprovers &&
|
|
275
|
+
config.additionalApprovers.length > 0) {
|
|
276
|
+
// Build multi-user AND condition: paymasterUserId AND all additionalApprovers must approve
|
|
277
|
+
const approverConditions = [
|
|
278
|
+
`approvers.any(user, user.id == '${config.paymasterUserId}')`,
|
|
279
|
+
...config.additionalApprovers.map((id) => `approvers.any(user, user.id == '${id}')`),
|
|
280
|
+
];
|
|
281
|
+
consensus = approverConditions.join(" && ");
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
// Default: only paymasterUserId can approve
|
|
285
|
+
consensus = `approvers.any(user, user.id == '${config.paymasterUserId}')`;
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
organizationId: config.organizationId,
|
|
289
|
+
policyName: config.policyName || "Gas Station Paymaster Execution Policy",
|
|
290
|
+
effect: "EFFECT_ALLOW",
|
|
291
|
+
consensus,
|
|
292
|
+
condition: conditions.join(" && "),
|
|
293
|
+
notes: "Restricts which execute() transactions the paymaster can submit on-chain",
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Retrieves an existing smart contract interface for the given contract address.
|
|
298
|
+
* Returns the interface ID if found, undefined otherwise.
|
|
299
|
+
*/
|
|
300
|
+
async function getSmartContractInterface({ client, organizationId, contractAddress, }) {
|
|
301
|
+
// Query ZeroXKey for existing interfaces
|
|
302
|
+
const response = await client.getSmartContractInterfaces({
|
|
303
|
+
organizationId,
|
|
304
|
+
});
|
|
305
|
+
// Find interface matching the contract address (case-insensitive)
|
|
306
|
+
const normalizedAddress = contractAddress.toLowerCase();
|
|
307
|
+
const existingInterface = response.smartContractInterfaces.find((iface) => iface.smartContractAddress.toLowerCase() === normalizedAddress);
|
|
308
|
+
if (existingInterface) {
|
|
309
|
+
return existingInterface.smartContractInterfaceId;
|
|
310
|
+
}
|
|
311
|
+
return undefined;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Uploads the Gas Station ABI to ZeroXKey as a Smart Contract Interface.
|
|
315
|
+
* Returns the newly created interface ID.
|
|
316
|
+
*/
|
|
317
|
+
async function uploadGasStationInterface({ client, organizationId, contractAddress, label, chainName, }) {
|
|
318
|
+
const defaultLabel = chainName
|
|
319
|
+
? `Gas Station - ${chainName}`
|
|
320
|
+
: `Gas Station - ${contractAddress}`;
|
|
321
|
+
const result = await client.createSmartContractInterface({
|
|
322
|
+
organizationId,
|
|
323
|
+
type: "SMART_CONTRACT_INTERFACE_TYPE_ETHEREUM",
|
|
324
|
+
label: label || defaultLabel,
|
|
325
|
+
notes: `EIP-7702 Gas Station execution contract ABI. Automatically uploaded by @0xkey-io/gas-station SDK.`,
|
|
326
|
+
smartContractAddress: contractAddress,
|
|
327
|
+
smartContractInterface: JSON.stringify(gasStationAbi),
|
|
328
|
+
});
|
|
329
|
+
const interfaceId = result.activity.result.createSmartContractInterfaceResult
|
|
330
|
+
?.smartContractInterfaceId;
|
|
331
|
+
if (!interfaceId) {
|
|
332
|
+
throw new Error("Failed to create smart contract interface: no interface ID returned");
|
|
333
|
+
}
|
|
334
|
+
return interfaceId;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Ensures that a Gas Station ABI is registered with ZeroXKey for the given contract.
|
|
338
|
+
* Checks if an interface already exists; if not, uploads it automatically.
|
|
339
|
+
* Returns the interface ID (existing or newly created).
|
|
340
|
+
*
|
|
341
|
+
* This function is called automatically by policy builders to enable ABI-based
|
|
342
|
+
* policy conditions that can directly access and compare function arguments.
|
|
343
|
+
*
|
|
344
|
+
* @param client - ZeroXKey API client (from 0xkeySDK.apiClient())
|
|
345
|
+
* @param organizationId - ZeroXKey organization ID
|
|
346
|
+
* @param contractAddress - Gas station contract address
|
|
347
|
+
* @param label - Optional custom label for the interface
|
|
348
|
+
* @param chainName - Optional chain name for labeling (e.g., "Base Mainnet")
|
|
349
|
+
* @returns The smart contract interface ID
|
|
350
|
+
*
|
|
351
|
+
* @example
|
|
352
|
+
* const interfaceId = await ensureGasStationInterface({
|
|
353
|
+
* client: 0xkeyClient.apiClient(),
|
|
354
|
+
* organizationId: "a5b89e4f-1234-5678-9abc-def012345678",
|
|
355
|
+
* contractAddress: "0x00000000008c57a1CE37836a5e9d36759D070d8c",
|
|
356
|
+
* chainName: "Base Sepolia"
|
|
357
|
+
* });
|
|
358
|
+
*/
|
|
359
|
+
async function ensureGasStationInterface({ client, organizationId, contractAddress, label, chainName, }) {
|
|
360
|
+
// Check if interface already exists
|
|
361
|
+
const existingId = await getSmartContractInterface({
|
|
362
|
+
client,
|
|
363
|
+
organizationId,
|
|
364
|
+
contractAddress,
|
|
365
|
+
});
|
|
366
|
+
if (existingId) {
|
|
367
|
+
return existingId;
|
|
368
|
+
}
|
|
369
|
+
// Upload new interface
|
|
370
|
+
return uploadGasStationInterface({
|
|
371
|
+
client,
|
|
372
|
+
organizationId,
|
|
373
|
+
contractAddress,
|
|
374
|
+
label: label || "",
|
|
375
|
+
chainName: chainName || "",
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export { buildIntentSigningPolicy, buildPaymasterExecutionPolicy, ensureGasStationInterface, getSmartContractInterface, uploadGasStationInterface };
|
|
380
|
+
//# sourceMappingURL=policyUtils.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policyUtils.mjs","sources":["../src/policyUtils.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@0xkey-io/gas-station",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "0xkey Gas Station SDK for EIP-7702 delegated execution",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"author": {
|
|
16
|
+
"name": "0xkey",
|
|
17
|
+
"url": "https://0xkey.com/"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/0xkey-io/sdk-js/tree/main/packages/gas-station",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/0xkey-io/sdk-js/issues"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/0xkey-io/sdk-js.git",
|
|
26
|
+
"directory": "packages/gas-station"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"keywords": [
|
|
32
|
+
"0xkey",
|
|
33
|
+
"gas-station",
|
|
34
|
+
"eip-7702",
|
|
35
|
+
"delegated-execution",
|
|
36
|
+
"paymaster",
|
|
37
|
+
"ethereum",
|
|
38
|
+
"viem"
|
|
39
|
+
],
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"viem": "^2.34.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/node": "^24.6.2",
|
|
45
|
+
"typescript": "^5.3.0",
|
|
46
|
+
"@0xkey-io/sdk-server": "0.1.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"viem": "^2.24.0",
|
|
50
|
+
"@0xkey-io/sdk-server": "0.1.0"
|
|
51
|
+
},
|
|
52
|
+
"license": "Apache-2.0",
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "rollup -c ../../rollup.config.base.mjs",
|
|
58
|
+
"typecheck": "tsc --noEmit",
|
|
59
|
+
"clean": "rimraf ./dist ./.cache"
|
|
60
|
+
}
|
|
61
|
+
}
|