@arcenpay/react 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/zerodev.mjs CHANGED
@@ -5,7 +5,8 @@ import {
5
5
  revokeAutopayModule,
6
6
  sendSmartAccountTransaction,
7
7
  updateAutopayConfig
8
- } from "./chunk-LACDYDLO.mjs";
8
+ } from "./chunk-JFY4DVS7.mjs";
9
+ import "./chunk-GY2HMODH.mjs";
9
10
  import "./chunk-X2BMVUAF.mjs";
10
11
  export {
11
12
  cancelSubscription,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcenpay/react",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "ArcenPay SDK — React components for Web3 subscription billing",
5
5
  "license": "UNLICENSED",
6
6
  "homepage": "https://app.arcenpay.com",
@@ -37,6 +37,11 @@
37
37
  "access": "public"
38
38
  },
39
39
  "scripts": {
40
+ "sync:core": "node ../../scripts/sync-sdk-core.mjs sdk-react",
41
+ "prebuild": "npm run sync:core",
42
+ "predev": "npm run sync:core",
43
+ "pretest": "npm run sync:core",
44
+ "pretypecheck": "npm run sync:core",
40
45
  "build": "tsup src/index.ts src/zerodev.ts --clean --format cjs,esm --dts --dts-resolve --external react --external @zerodev/sdk --external @zerodev/ecdsa-validator",
41
46
  "dev": "tsup src/index.ts src/zerodev.ts --clean --format cjs,esm --dts --external react --external @zerodev/sdk --external @zerodev/ecdsa-validator --watch",
42
47
  "test": "vitest run",
@@ -58,7 +63,6 @@
58
63
  }
59
64
  },
60
65
  "dependencies": {
61
- "@arcenpay/sdk": "0.0.1",
62
66
  "@tanstack/react-query": "^5.62.0",
63
67
  "viem": "^2.21.0",
64
68
  "wagmi": "^2.14.0"
@@ -1,402 +0,0 @@
1
- // src/lib/zerodev.ts
2
- import {
3
- createKernelAccount,
4
- createKernelAccountClient,
5
- createZeroDevPaymasterClient,
6
- constants as zeroDevConstants
7
- } from "@zerodev/sdk";
8
- import { signerToEcdsaValidator } from "@zerodev/ecdsa-validator";
9
- import {
10
- createPublicClient,
11
- http,
12
- encodeFunctionData
13
- } from "viem";
14
- import { sepolia, baseSepolia, base } from "viem/chains";
15
- import {
16
- getContractAddresses,
17
- ERC7579AutopayModuleABI,
18
- SubscriptionRegistryABI
19
- } from "@arcenpay/sdk";
20
- var CHAIN_MAP = {
21
- 11155111: sepolia,
22
- 84532: baseSepolia,
23
- 8453: base
24
- };
25
- var ENTRY_POINT = zeroDevConstants.getEntryPoint("0.7");
26
- var ENTRY_POINT_ADDRESS = ENTRY_POINT.address;
27
- var KERNEL_VERSION = zeroDevConstants.KERNEL_V3_1;
28
- function getZeroDevChainLabel(chainId) {
29
- if (chainId === 84532) return "Base Sepolia";
30
- if (chainId === 8453) return "Base";
31
- if (chainId === 11155111) return "Sepolia";
32
- return `Chain ${chainId}`;
33
- }
34
- function resolveZeroDevUrls(params) {
35
- const specificUnified = process.env[`NEXT_PUBLIC_ZERODEV_RPC_${params.chainId}`];
36
- const specificBundler = process.env[`NEXT_PUBLIC_ZERODEV_BUNDLER_RPC_${params.chainId}`];
37
- const specificPaymaster = process.env[`NEXT_PUBLIC_ZERODEV_PAYMASTER_RPC_${params.chainId}`];
38
- const genericUnified = process.env.NEXT_PUBLIC_ZERODEV_RPC;
39
- const genericBundler = process.env.NEXT_PUBLIC_ZERODEV_BUNDLER_RPC;
40
- const genericPaymaster = process.env.NEXT_PUBLIC_ZERODEV_PAYMASTER_RPC;
41
- const defaultUnifiedV3 = `https://rpc.zerodev.app/api/v3/${params.projectId}/chain/${params.chainId}`;
42
- const hasConfiguredUrls = !!(params.bundlerUrl || params.paymasterUrl || specificUnified || specificBundler || specificPaymaster || genericUnified || genericBundler || genericPaymaster);
43
- return {
44
- bundlerUrl: params.bundlerUrl || specificUnified || specificBundler || genericUnified || genericBundler || defaultUnifiedV3 || `https://rpc.zerodev.app/api/v2/bundler/${params.projectId}`,
45
- paymasterUrl: params.paymasterUrl || specificUnified || specificPaymaster || genericUnified || genericPaymaster || defaultUnifiedV3 || `https://rpc.zerodev.app/api/v2/paymaster/${params.projectId}`,
46
- hasConfiguredUrls
47
- };
48
- }
49
- function normalizeZeroDevError(error, params) {
50
- const message = error instanceof Error ? error.message : String(error ?? "");
51
- const chainLabel = getZeroDevChainLabel(params.chainId);
52
- const usingDefaultUrls = !params.hasConfiguredUrls;
53
- if (message.includes("ChainId not found")) {
54
- const nextStep = usingDefaultUrls ? `Enable ${chainLabel} for ZeroDev project ${params.projectId}, or set NEXT_PUBLIC_ZERODEV_BUNDLER_RPC_${params.chainId} and NEXT_PUBLIC_ZERODEV_PAYMASTER_RPC_${params.chainId} to chain-specific endpoints.` : `The configured ZeroDev endpoint does not recognize ${chainLabel} for project ${params.projectId}. Verify the project supports chain ${params.chainId} or replace the override URLs. Bundler URL: ${params.bundlerUrl ?? "n/a"}. Paymaster URL: ${params.paymasterUrl ?? "n/a"}.`;
55
- return new Error(
56
- `ZeroDev project ${params.projectId} is not configured for ${chainLabel} (chain ${params.chainId}). ${nextStep}`
57
- );
58
- }
59
- return error instanceof Error ? error : new Error(message);
60
- }
61
- function isRecoverableSmartAccountFundingError(error) {
62
- const message = error instanceof Error ? error.message : String(error ?? "");
63
- const lower = message.toLowerCase();
64
- return lower.includes("smart account does not have sufficient funds") || lower.includes("sufficient funds to execute the user operation") || lower.includes("insufficient funds") || lower.includes("user operation") && lower.includes("paymaster");
65
- }
66
- async function createKernelExecutionContext(config) {
67
- const chain = CHAIN_MAP[config.chainId] || baseSepolia;
68
- const { bundlerUrl, paymasterUrl, hasConfiguredUrls } = resolveZeroDevUrls({
69
- projectId: config.projectId,
70
- chainId: config.chainId,
71
- bundlerUrl: config.bundlerUrl,
72
- paymasterUrl: config.paymasterUrl
73
- });
74
- const publicClient = createPublicClient({
75
- chain,
76
- transport: http()
77
- });
78
- const ecdsaValidator = await signerToEcdsaValidator(publicClient, {
79
- signer: config.walletClient,
80
- entryPoint: ENTRY_POINT,
81
- kernelVersion: KERNEL_VERSION
82
- });
83
- const kernelAccount = await createKernelAccount(publicClient, {
84
- plugins: { sudo: ecdsaValidator },
85
- entryPoint: ENTRY_POINT,
86
- kernelVersion: KERNEL_VERSION
87
- });
88
- const paymasterClient = createZeroDevPaymasterClient({
89
- chain,
90
- transport: http(paymasterUrl)
91
- });
92
- const kernelClient = createKernelAccountClient({
93
- account: kernelAccount,
94
- chain,
95
- bundlerTransport: http(bundlerUrl),
96
- middleware: {
97
- sponsorUserOperation: async ({ userOperation }) => {
98
- return paymasterClient.sponsorUserOperation({
99
- userOperation,
100
- entryPoint: ENTRY_POINT_ADDRESS
101
- });
102
- }
103
- }
104
- });
105
- return {
106
- publicClient,
107
- kernelAccount,
108
- kernelClient,
109
- bundlerUrl,
110
- paymasterUrl,
111
- hasConfiguredUrls
112
- };
113
- }
114
- async function deploySmartAccount(config) {
115
- const chain = CHAIN_MAP[config.chainId] || baseSepolia;
116
- const contracts = getContractAddresses(config.chainId);
117
- const { bundlerUrl, paymasterUrl, hasConfiguredUrls } = resolveZeroDevUrls({
118
- projectId: config.projectId,
119
- chainId: config.chainId,
120
- bundlerUrl: config.bundlerUrl,
121
- paymasterUrl: config.paymasterUrl
122
- });
123
- const publicClient = createPublicClient({
124
- chain,
125
- transport: http()
126
- });
127
- const ecdsaValidator = await signerToEcdsaValidator(publicClient, {
128
- signer: config.walletClient,
129
- entryPoint: ENTRY_POINT,
130
- kernelVersion: KERNEL_VERSION
131
- });
132
- const kernelAccount = await createKernelAccount(publicClient, {
133
- plugins: {
134
- sudo: ecdsaValidator
135
- },
136
- entryPoint: ENTRY_POINT,
137
- kernelVersion: KERNEL_VERSION
138
- });
139
- const smartAccountAddress = kernelAccount.address;
140
- const code = await publicClient.getCode({ address: smartAccountAddress });
141
- const alreadyDeployed = !!code && code !== "0x";
142
- const paymasterClient = createZeroDevPaymasterClient({
143
- chain,
144
- transport: http(paymasterUrl)
145
- });
146
- const kernelClient = createKernelAccountClient({
147
- account: kernelAccount,
148
- chain,
149
- bundlerTransport: http(bundlerUrl),
150
- middleware: {
151
- sponsorUserOperation: async ({ userOperation }) => {
152
- return paymasterClient.sponsorUserOperation({
153
- userOperation,
154
- entryPoint: ENTRY_POINT_ADDRESS
155
- });
156
- }
157
- }
158
- });
159
- let installTxHash;
160
- if (contracts.autopayModule) {
161
- try {
162
- const initialized = await publicClient.readContract({
163
- address: contracts.autopayModule,
164
- abi: ERC7579AutopayModuleABI,
165
- functionName: "isInitialized",
166
- args: [smartAccountAddress]
167
- });
168
- if (initialized) {
169
- console.log(
170
- `[ZeroDev] AutopayModule already initialized for ${smartAccountAddress}`
171
- );
172
- return {
173
- smartAccountAddress,
174
- installTxHash,
175
- alreadyDeployed
176
- };
177
- }
178
- const installData = encodeFunctionData({
179
- abi: [
180
- {
181
- type: "function",
182
- name: "installModule",
183
- inputs: [
184
- { name: "moduleType", type: "uint256" },
185
- { name: "module", type: "address" },
186
- { name: "initData", type: "bytes" }
187
- ],
188
- outputs: [],
189
- stateMutability: "nonpayable"
190
- }
191
- ],
192
- functionName: "installModule",
193
- args: [
194
- 2n,
195
- // Module type 2 = Executor
196
- contracts.autopayModule,
197
- "0x"
198
- // Empty init data
199
- ]
200
- });
201
- installTxHash = await kernelClient.sendTransaction({
202
- to: smartAccountAddress,
203
- data: installData,
204
- value: 0n
205
- });
206
- console.log(
207
- `[ZeroDev] AutopayModule installed on ${smartAccountAddress} \u2014 tx: ${installTxHash}`
208
- );
209
- } catch (err) {
210
- if (err?.message?.includes("already installed") || err?.message?.includes("AlreadyInitialized")) {
211
- console.log(
212
- `[ZeroDev] AutopayModule already installed on ${smartAccountAddress}`
213
- );
214
- } else {
215
- const normalizedError = normalizeZeroDevError(err, {
216
- projectId: config.projectId,
217
- chainId: config.chainId,
218
- bundlerUrl,
219
- paymasterUrl,
220
- hasConfiguredUrls
221
- });
222
- if (isRecoverableSmartAccountFundingError(normalizedError)) {
223
- console.warn(
224
- "[ZeroDev] Module installation needs prefund or sponsorship; callers may fall back to the connected wallet:",
225
- normalizedError.message
226
- );
227
- } else {
228
- console.error("[ZeroDev] Module installation failed:", normalizedError.message);
229
- }
230
- throw normalizedError;
231
- }
232
- }
233
- }
234
- return {
235
- smartAccountAddress,
236
- installTxHash,
237
- alreadyDeployed
238
- };
239
- }
240
- async function revokeAutopayModule(config) {
241
- const chain = CHAIN_MAP[config.chainId] || baseSepolia;
242
- const contracts = getContractAddresses(config.chainId);
243
- if (!contracts.autopayModule) {
244
- throw new Error("Autopay module address not configured for this chain.");
245
- }
246
- const { bundlerUrl, paymasterUrl, hasConfiguredUrls } = resolveZeroDevUrls({
247
- projectId: config.projectId,
248
- chainId: config.chainId,
249
- bundlerUrl: config.bundlerUrl,
250
- paymasterUrl: config.paymasterUrl
251
- });
252
- const publicClient = createPublicClient({
253
- chain,
254
- transport: http()
255
- });
256
- const initialized = await publicClient.readContract({
257
- address: contracts.autopayModule,
258
- abi: ERC7579AutopayModuleABI,
259
- functionName: "isInitialized",
260
- args: [config.smartAccountAddress]
261
- });
262
- if (!initialized) {
263
- return { alreadyRevoked: true };
264
- }
265
- const { kernelAccount, kernelClient } = await createKernelExecutionContext({
266
- projectId: config.projectId,
267
- chainId: config.chainId,
268
- walletClient: config.walletClient,
269
- bundlerUrl,
270
- paymasterUrl
271
- });
272
- if (kernelAccount.address.toLowerCase() !== config.smartAccountAddress.toLowerCase()) {
273
- throw new Error(
274
- `Kernel account mismatch. Expected ${config.smartAccountAddress}, got ${kernelAccount.address}.`
275
- );
276
- }
277
- const revokeData = encodeFunctionData({
278
- abi: ERC7579AutopayModuleABI,
279
- functionName: "onUninstall",
280
- args: ["0x"]
281
- });
282
- try {
283
- const txHash = await kernelClient.sendTransaction({
284
- to: contracts.autopayModule,
285
- data: revokeData,
286
- value: 0n
287
- });
288
- return { txHash, alreadyRevoked: false };
289
- } catch (error) {
290
- throw normalizeZeroDevError(error, {
291
- projectId: config.projectId,
292
- chainId: config.chainId,
293
- bundlerUrl,
294
- paymasterUrl,
295
- hasConfiguredUrls
296
- });
297
- }
298
- }
299
- async function sendSmartAccountTransaction(config) {
300
- const {
301
- publicClient,
302
- kernelAccount,
303
- kernelClient,
304
- bundlerUrl,
305
- paymasterUrl,
306
- hasConfiguredUrls
307
- } = await createKernelExecutionContext({
308
- projectId: config.projectId,
309
- chainId: config.chainId,
310
- walletClient: config.walletClient,
311
- bundlerUrl: config.bundlerUrl,
312
- paymasterUrl: config.paymasterUrl
313
- });
314
- if (config.smartAccountAddress && kernelAccount.address.toLowerCase() !== config.smartAccountAddress.toLowerCase()) {
315
- throw new Error(
316
- `Kernel account mismatch. Expected ${config.smartAccountAddress}, got ${kernelAccount.address}.`
317
- );
318
- }
319
- try {
320
- const txHash = await kernelClient.sendTransaction({
321
- to: config.to,
322
- data: config.data,
323
- value: config.value ?? 0n
324
- });
325
- await publicClient.waitForTransactionReceipt({ hash: txHash });
326
- return {
327
- smartAccountAddress: kernelAccount.address,
328
- txHash
329
- };
330
- } catch (error) {
331
- throw normalizeZeroDevError(error, {
332
- projectId: config.projectId,
333
- chainId: config.chainId,
334
- bundlerUrl,
335
- paymasterUrl,
336
- hasConfiguredUrls
337
- });
338
- }
339
- }
340
- async function updateAutopayConfig(config) {
341
- const contracts = getContractAddresses(config.chainId);
342
- if (!contracts.autopayModule) {
343
- throw new Error("Autopay module address is not configured for this chain.");
344
- }
345
- const data = encodeFunctionData({
346
- abi: ERC7579AutopayModuleABI,
347
- functionName: "updateConfig",
348
- args: [
349
- {
350
- merchant: config.merchant,
351
- maxAmount: config.maxAmount,
352
- token: config.token,
353
- interval: config.interval,
354
- startTime: config.startTime,
355
- planId: config.planId,
356
- maxTotalAmount: config.maxTotalAmount ?? 0n
357
- }
358
- ]
359
- });
360
- return sendSmartAccountTransaction({
361
- projectId: config.projectId,
362
- chainId: config.chainId,
363
- walletClient: config.walletClient,
364
- smartAccountAddress: config.smartAccountAddress,
365
- to: contracts.autopayModule,
366
- data,
367
- bundlerUrl: config.bundlerUrl,
368
- paymasterUrl: config.paymasterUrl
369
- });
370
- }
371
- async function cancelSubscription(config) {
372
- const contracts = getContractAddresses(config.chainId);
373
- if (!contracts.subscriptionRegistry) {
374
- throw new Error(
375
- "Subscription registry address is not configured for this chain."
376
- );
377
- }
378
- const data = encodeFunctionData({
379
- abi: SubscriptionRegistryABI,
380
- functionName: "cancelSubscription",
381
- args: [config.tokenId]
382
- });
383
- return sendSmartAccountTransaction({
384
- projectId: config.projectId,
385
- chainId: config.chainId,
386
- walletClient: config.walletClient,
387
- smartAccountAddress: config.smartAccountAddress,
388
- to: contracts.subscriptionRegistry,
389
- data,
390
- bundlerUrl: config.bundlerUrl,
391
- paymasterUrl: config.paymasterUrl
392
- });
393
- }
394
-
395
- export {
396
- isRecoverableSmartAccountFundingError,
397
- deploySmartAccount,
398
- revokeAutopayModule,
399
- sendSmartAccountTransaction,
400
- updateAutopayConfig,
401
- cancelSubscription
402
- };
File without changes