@volr/react 0.1.21 → 0.1.23

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/index.js CHANGED
@@ -17921,6 +17921,8 @@ function http(url, config = {}) {
17921
17921
  // ../node_modules/viem/_esm/index.js
17922
17922
  init_encodeFunctionData();
17923
17923
  init_getAddress();
17924
+ init_formatEther();
17925
+ init_formatUnits();
17924
17926
 
17925
17927
  // src/utils/normalize.ts
17926
17928
  function normalizeHex(value) {
@@ -18078,112 +18080,6 @@ function normalizeCall(call2) {
18078
18080
  function normalizeCalls(calls) {
18079
18081
  return calls.map(normalizeCall);
18080
18082
  }
18081
-
18082
- // src/wallet/preflight.ts
18083
- function extractErrorMessage(err) {
18084
- if (err && typeof err === "object") {
18085
- const e = err;
18086
- const parts = [];
18087
- if (typeof e.shortMessage === "string") parts.push(e.shortMessage);
18088
- if (typeof e.message === "string") parts.push(e.message);
18089
- if (typeof e.cause?.message === "string") parts.push(e.cause.message);
18090
- if (typeof e.details === "string") parts.push(e.details);
18091
- const msg = parts.filter(Boolean).join(" | ");
18092
- if (msg) return msg;
18093
- }
18094
- try {
18095
- return String(err);
18096
- } catch {
18097
- return "Unknown error";
18098
- }
18099
- }
18100
- function isIgnorableFundingError(err, message) {
18101
- const m = message.toLowerCase();
18102
- const e = err;
18103
- const name = typeof e?.name === "string" ? e.name.toLowerCase() : "";
18104
- if (name === "insufficientfundserror" || name.includes("insufficientfunds")) {
18105
- return true;
18106
- }
18107
- if (typeof e?.code === "string") {
18108
- const code = e.code.toLowerCase();
18109
- if (code.includes("execution_reverted") || code.includes("call_exception")) {
18110
- return false;
18111
- }
18112
- if (code.includes("insufficient_funds")) {
18113
- return true;
18114
- }
18115
- }
18116
- const fundingPatterns = [
18117
- "insufficient funds for gas * price",
18118
- "insufficient funds for gas",
18119
- "for gas * price + value",
18120
- "not enough funds for l1 fee",
18121
- "insufficient funds for l1 fee",
18122
- "insufficient balance for gas",
18123
- "account balance too low"
18124
- ];
18125
- const hasFundingPattern = fundingPatterns.some((pattern) => m.includes(pattern));
18126
- const hasRevertIndicator = m.includes("revert") || m.includes("execution reverted") || m.includes("call exception") || m.includes("vm execution error");
18127
- return hasFundingPattern && !hasRevertIndicator;
18128
- }
18129
- async function preflightEstimate(publicClient, from14, calls, opts) {
18130
- for (let i = 0; i < calls.length; i++) {
18131
- const c = calls[i];
18132
- try {
18133
- await publicClient.estimateGas({
18134
- account: from14,
18135
- to: c.target,
18136
- data: c.data,
18137
- value: c.value ?? 0n
18138
- });
18139
- } catch (e) {
18140
- const message = extractErrorMessage(e);
18141
- const tolerateFunding = opts?.tolerateFundingErrors !== false;
18142
- const isFundingError = isIgnorableFundingError(e, message);
18143
- if (tolerateFunding && isFundingError) {
18144
- try {
18145
- await publicClient.call({
18146
- account: from14,
18147
- to: c.target,
18148
- data: c.data,
18149
- value: c.value ?? 0n
18150
- });
18151
- console.log(
18152
- `[preflightEstimate] Ignoring funding error for call #${i} (target ${c.target}): ${message}`
18153
- );
18154
- continue;
18155
- } catch (callError) {
18156
- const callMessage = extractErrorMessage(callError);
18157
- console.error(
18158
- `[preflightEstimate] Static call after funding error also failed for call #${i} (target ${c.target}):`,
18159
- {
18160
- originalError: { message, errorName: e?.name, errorCode: e?.code },
18161
- callError: {
18162
- message: callMessage,
18163
- name: callError?.name,
18164
- code: callError?.code
18165
- }
18166
- }
18167
- );
18168
- throw new Error(
18169
- `Preflight failed (call #${i} target ${c.target}): ${callMessage}`
18170
- );
18171
- }
18172
- }
18173
- console.error(
18174
- `[preflightEstimate] Preflight failed for call #${i} (target ${c.target}):`,
18175
- {
18176
- message,
18177
- errorName: e?.name,
18178
- errorCode: e?.code,
18179
- isFundingError,
18180
- tolerateFunding
18181
- }
18182
- );
18183
- throw new Error(`Preflight failed (call #${i} target ${c.target}): ${message}`);
18184
- }
18185
- }
18186
- }
18187
18083
  async function resolveSigner(input) {
18188
18084
  const { explicitSigner, provider, chainId, client, user, setProvider } = input;
18189
18085
  if (explicitSigner) {
@@ -18280,6 +18176,40 @@ function finalizeAuthWithNonce(tempAuth, quote) {
18280
18176
  }
18281
18177
 
18282
18178
  // src/utils/tx-polling.ts
18179
+ function extractFailureReason(response) {
18180
+ const reasons = [];
18181
+ const meta = response.meta;
18182
+ if (meta) {
18183
+ if (typeof meta.revertReason === "string" && meta.revertReason) {
18184
+ reasons.push(meta.revertReason);
18185
+ }
18186
+ if (typeof meta.failureReason === "string" && meta.failureReason) {
18187
+ reasons.push(meta.failureReason);
18188
+ }
18189
+ const diag = meta.developerDiagnostics;
18190
+ if (diag) {
18191
+ if (typeof diag.revertReason === "string" && diag.revertReason) {
18192
+ reasons.push(diag.revertReason);
18193
+ }
18194
+ if (typeof diag.error === "string" && diag.error) {
18195
+ reasons.push(diag.error);
18196
+ }
18197
+ const simErrors = diag.simulationErrors;
18198
+ if (Array.isArray(simErrors)) {
18199
+ for (const err of simErrors) {
18200
+ if (typeof err.error === "string") {
18201
+ reasons.push(`Simulation error: ${err.error}`);
18202
+ }
18203
+ }
18204
+ }
18205
+ }
18206
+ }
18207
+ const uniqueReasons = [...new Set(reasons)];
18208
+ if (uniqueReasons.length > 0) {
18209
+ return uniqueReasons.join("; ");
18210
+ }
18211
+ return "Transaction failed on-chain (no specific reason provided)";
18212
+ }
18283
18213
  async function pollTransactionStatus(txId, client, maxAttempts = 60, intervalMs = 5e3) {
18284
18214
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
18285
18215
  try {
@@ -18296,15 +18226,17 @@ async function pollTransactionStatus(txId, client, maxAttempts = 60, intervalMs
18296
18226
  };
18297
18227
  }
18298
18228
  if (status === "FAILED") {
18299
- console.error(`[pollTransactionStatus] Transaction ${txId} failed`);
18300
- const diag = response.meta?.developerDiagnostics;
18301
- if (diag) {
18302
- console.error("[volr][relay] developerDiagnostics:", diag);
18229
+ const failureReason = extractFailureReason(response);
18230
+ console.error(`[pollTransactionStatus] Transaction ${txId} failed: ${failureReason}`);
18231
+ const meta = response.meta;
18232
+ if (meta) {
18233
+ console.error("[pollTransactionStatus] Full meta:", JSON.stringify(meta, null, 2));
18303
18234
  }
18304
18235
  return {
18305
18236
  txId,
18306
18237
  status: "FAILED",
18307
- txHash
18238
+ txHash,
18239
+ reason: failureReason
18308
18240
  };
18309
18241
  }
18310
18242
  console.log(`[pollTransactionStatus] Transaction ${txId} is ${status}, attempt ${attempt + 1}/${maxAttempts}`);
@@ -18354,19 +18286,6 @@ async function sendCalls(args) {
18354
18286
  keyStorageType: deps.user?.keyStorageType
18355
18287
  });
18356
18288
  }
18357
- if (opts.preflight !== false) {
18358
- console.log("[sendCalls] Running preflight estimate...");
18359
- const tolerateFundingErrors = (opts.mode ?? "sponsored") !== "self";
18360
- await preflightEstimate(
18361
- deps.publicClient,
18362
- normalizedFrom,
18363
- normalizedCalls,
18364
- { tolerateFundingErrors }
18365
- );
18366
- console.log("[sendCalls] Preflight estimate done");
18367
- } else {
18368
- console.log("[sendCalls] Preflight skipped");
18369
- }
18370
18289
  console.log("[sendCalls] Building temp auth for first precheck...");
18371
18290
  const tempAuthForPrecheck = buildTempAuth({
18372
18291
  chainId,
@@ -18382,11 +18301,34 @@ async function sendCalls(args) {
18382
18301
  auth: tempAuthForPrecheck,
18383
18302
  calls: normalizedCalls
18384
18303
  });
18385
- console.log("[sendCalls] First precheck done, policyId:", precheckQuote.policyId);
18304
+ console.log("[sendCalls] First precheck done:", {
18305
+ policyId: precheckQuote.policyId,
18306
+ simulationSuccess: precheckQuote.simulationSuccess,
18307
+ estimatedGasPerCall: precheckQuote.estimatedGasPerCall
18308
+ });
18386
18309
  } catch (err) {
18387
18310
  console.error("[sendCalls] First precheck failed:", err);
18388
18311
  throw err instanceof Error ? err : new Error(String(err));
18389
18312
  }
18313
+ if (precheckQuote.simulationSuccess === false && precheckQuote.simulationErrors?.length) {
18314
+ const errors = precheckQuote.simulationErrors;
18315
+ console.warn("[sendCalls] Backend simulation failed (this may be expected for EIP-7702 transactions):", errors);
18316
+ for (const err of errors) {
18317
+ console.warn(`[sendCalls] Call #${err.index}: ${err.error}${err.revertData ? ` (revert data: ${err.revertData})` : ""}`);
18318
+ }
18319
+ console.warn("[sendCalls] Proceeding despite simulation failure - EIP-7702 execution context may differ");
18320
+ }
18321
+ if (precheckQuote.estimatedGasPerCall?.length) {
18322
+ console.log("[sendCalls] Applying estimated gas limits from backend...");
18323
+ for (let i = 0; i < normalizedCalls.length && i < precheckQuote.estimatedGasPerCall.length; i++) {
18324
+ const estimatedGas = BigInt(precheckQuote.estimatedGasPerCall[i] ?? "0");
18325
+ const currentGas = normalizedCalls[i]?.gasLimit ?? 0n;
18326
+ if (estimatedGas > currentGas) {
18327
+ console.log(`[sendCalls] Call #${i}: updating gasLimit from ${currentGas} to ${estimatedGas}`);
18328
+ normalizedCalls[i].gasLimit = estimatedGas;
18329
+ }
18330
+ }
18331
+ }
18390
18332
  const quotePolicyId = precheckQuote.policyId;
18391
18333
  if (!quotePolicyId) {
18392
18334
  throw new Error("Backend did not return policyId in precheck response");
@@ -18399,6 +18341,7 @@ async function sendCalls(args) {
18399
18341
  from: normalizedFrom,
18400
18342
  policyId: projectPolicyId,
18401
18343
  calls: normalizedCalls,
18344
+ // Now with updated gas limits
18402
18345
  expiresInSec: opts.expiresInSec ?? DEFAULT_EXPIRES_IN_SEC
18403
18346
  });
18404
18347
  let quote;
@@ -19366,6 +19309,219 @@ async function uploadBlobViaPresign(params) {
19366
19309
  }
19367
19310
  return { s3Key };
19368
19311
  }
19312
+
19313
+ // src/utils/contract-analysis.ts
19314
+ var EIP7702_PREFIX = "0xef0100";
19315
+ async function isEIP7702Delegated(publicClient, address) {
19316
+ try {
19317
+ const code = await publicClient.getCode({ address });
19318
+ if (!code || code === "0x" || code.length < 8) {
19319
+ return false;
19320
+ }
19321
+ return code.toLowerCase().startsWith(EIP7702_PREFIX);
19322
+ } catch {
19323
+ return false;
19324
+ }
19325
+ }
19326
+ async function analyzeContractForEIP7702(publicClient, target, calldata) {
19327
+ const notes = [];
19328
+ let isContract = false;
19329
+ let codeSize = 0;
19330
+ let mayCheckSenderCode = false;
19331
+ let mayUseDelegationGuard = false;
19332
+ try {
19333
+ const code = await publicClient.getCode({ address: target });
19334
+ isContract = !!code && code !== "0x";
19335
+ codeSize = code ? (code.length - 2) / 2 : 0;
19336
+ if (!isContract || !code) {
19337
+ notes.push("Target is not a contract (EOA or empty address)");
19338
+ } else {
19339
+ const codeLower = code.toLowerCase();
19340
+ if (codeLower.includes("3b")) {
19341
+ mayCheckSenderCode = true;
19342
+ notes.push("Contract contains EXTCODESIZE opcode - may check msg.sender.code.length");
19343
+ }
19344
+ if (codeLower.includes("ef0100")) {
19345
+ mayUseDelegationGuard = true;
19346
+ notes.push("Contract contains EIP-7702 prefix bytes - may use DelegationGuard pattern");
19347
+ }
19348
+ }
19349
+ } catch (error) {
19350
+ notes.push(`Failed to fetch contract code: ${error instanceof Error ? error.message : "Unknown error"}`);
19351
+ }
19352
+ const functionSelector = calldata && calldata.length >= 10 ? calldata.slice(0, 10) : "0x";
19353
+ return {
19354
+ target,
19355
+ isContract,
19356
+ codeSize,
19357
+ mayCheckSenderCode,
19358
+ mayUseDelegationGuard,
19359
+ functionSelector,
19360
+ notes
19361
+ };
19362
+ }
19363
+ async function diagnoseTransactionFailure(publicClient, from14, target, calldata) {
19364
+ const recommendations = [];
19365
+ const fromCode = await publicClient.getCode({ address: from14 });
19366
+ const fromHasCode = !!fromCode && fromCode !== "0x";
19367
+ const fromIsDelegated = await isEIP7702Delegated(publicClient, from14);
19368
+ const targetAnalysis = await analyzeContractForEIP7702(publicClient, target, calldata);
19369
+ if (!targetAnalysis.isContract) {
19370
+ recommendations.push("Target is not a contract. Verify the target address is correct.");
19371
+ }
19372
+ if (targetAnalysis.mayCheckSenderCode) {
19373
+ recommendations.push(
19374
+ "Target contract may check msg.sender.code.length. This can cause issues because in EIP-7702, the sender EOA temporarily has code."
19375
+ );
19376
+ }
19377
+ if (targetAnalysis.mayUseDelegationGuard) {
19378
+ recommendations.push(
19379
+ "Target contract may use DelegationGuard pattern to block EIP-7702 delegated accounts. This is a security measure some contracts use. You may need to contact the contract developers or use a different approach."
19380
+ );
19381
+ }
19382
+ if (!fromIsDelegated && fromHasCode) {
19383
+ recommendations.push(
19384
+ "Sender address has code but is not EIP-7702 delegated. This may indicate the address is a contract, not an EOA."
19385
+ );
19386
+ }
19387
+ if (recommendations.length === 0) {
19388
+ recommendations.push(
19389
+ "No obvious EIP-7702 compatibility issues detected. The failure may be due to contract logic (e.g., insufficient balance, invalid parameters). Check the contract's requirements and your transaction parameters."
19390
+ );
19391
+ }
19392
+ return {
19393
+ fromAnalysis: {
19394
+ isDelegated: fromIsDelegated,
19395
+ hasCode: fromHasCode
19396
+ },
19397
+ targetAnalysis,
19398
+ recommendations
19399
+ };
19400
+ }
19401
+
19402
+ // src/utils/wallet-debug.ts
19403
+ async function getWalletState(publicClient, address) {
19404
+ const [balance, code, nonce] = await Promise.all([
19405
+ publicClient.getBalance({ address }),
19406
+ publicClient.getCode({ address }),
19407
+ publicClient.getTransactionCount({ address })
19408
+ ]);
19409
+ const hasCode = !!code && code !== "0x";
19410
+ const codeLength = code ? (code.length - 2) / 2 : 0;
19411
+ const isEIP7702Delegated2 = hasCode && code.toLowerCase().startsWith("0xef0100");
19412
+ return {
19413
+ address,
19414
+ ethBalance: formatEther(balance),
19415
+ ethBalanceWei: balance,
19416
+ hasCode,
19417
+ codeLength,
19418
+ nonce,
19419
+ isEIP7702Delegated: isEIP7702Delegated2
19420
+ };
19421
+ }
19422
+ async function getERC20Balance(publicClient, walletAddress, tokenAddress, decimals = 18) {
19423
+ const balance = await publicClient.readContract({
19424
+ address: tokenAddress,
19425
+ abi: [
19426
+ {
19427
+ name: "balanceOf",
19428
+ type: "function",
19429
+ stateMutability: "view",
19430
+ inputs: [{ name: "account", type: "address" }],
19431
+ outputs: [{ type: "uint256" }]
19432
+ }
19433
+ ],
19434
+ functionName: "balanceOf",
19435
+ args: [walletAddress]
19436
+ });
19437
+ return {
19438
+ address: walletAddress,
19439
+ tokenAddress,
19440
+ balance: formatUnits(balance, decimals),
19441
+ balanceRaw: balance,
19442
+ decimals
19443
+ };
19444
+ }
19445
+ async function compareWalletStates(publicClient, address1, address2) {
19446
+ const [wallet1, wallet2] = await Promise.all([
19447
+ getWalletState(publicClient, address1),
19448
+ getWalletState(publicClient, address2)
19449
+ ]);
19450
+ const differences = [];
19451
+ if (wallet1.hasCode !== wallet2.hasCode) {
19452
+ differences.push(
19453
+ `Code presence differs: ${address1} has ${wallet1.hasCode ? "code" : "no code"}, ${address2} has ${wallet2.hasCode ? "code" : "no code"}`
19454
+ );
19455
+ }
19456
+ if (wallet1.isEIP7702Delegated !== wallet2.isEIP7702Delegated) {
19457
+ differences.push(
19458
+ `EIP-7702 delegation differs: ${address1} is ${wallet1.isEIP7702Delegated ? "" : "not "}delegated, ${address2} is ${wallet2.isEIP7702Delegated ? "" : "not "}delegated`
19459
+ );
19460
+ }
19461
+ const balanceDiff = wallet1.ethBalanceWei - wallet2.ethBalanceWei;
19462
+ if (balanceDiff !== 0n) {
19463
+ differences.push(
19464
+ `ETH balance differs by ${formatEther(balanceDiff > 0n ? balanceDiff : -balanceDiff)} ETH`
19465
+ );
19466
+ }
19467
+ return { wallet1, wallet2, differences };
19468
+ }
19469
+ async function compareERC20Balances(publicClient, address1, address2, tokenAddress, decimals = 18) {
19470
+ const [wallet1, wallet2] = await Promise.all([
19471
+ getERC20Balance(publicClient, address1, tokenAddress, decimals),
19472
+ getERC20Balance(publicClient, address2, tokenAddress, decimals)
19473
+ ]);
19474
+ const differenceRaw = wallet1.balanceRaw - wallet2.balanceRaw;
19475
+ return {
19476
+ wallet1,
19477
+ wallet2,
19478
+ difference: formatUnits(differenceRaw > 0n ? differenceRaw : -differenceRaw, decimals),
19479
+ differenceRaw
19480
+ };
19481
+ }
19482
+ async function debugTransactionFailure(publicClient, failingWallet, workingWallet, tokenAddress, tokenDecimals = 18) {
19483
+ const analysis = [];
19484
+ const stateComparison = await compareWalletStates(
19485
+ publicClient,
19486
+ failingWallet,
19487
+ workingWallet
19488
+ );
19489
+ if (stateComparison.wallet1.isEIP7702Delegated && !stateComparison.wallet2.isEIP7702Delegated) {
19490
+ analysis.push(
19491
+ "The failing wallet has EIP-7702 delegation while the working wallet does not. This may cause issues if the target contract checks msg.sender.code.length or uses DelegationGuard."
19492
+ );
19493
+ }
19494
+ if (stateComparison.wallet1.hasCode && !stateComparison.wallet2.hasCode) {
19495
+ analysis.push(
19496
+ "The failing wallet has code while the working wallet is a pure EOA. Some contracts reject calls from addresses with code."
19497
+ );
19498
+ }
19499
+ let tokenComparison;
19500
+ if (tokenAddress) {
19501
+ tokenComparison = await compareERC20Balances(
19502
+ publicClient,
19503
+ failingWallet,
19504
+ workingWallet,
19505
+ tokenAddress,
19506
+ tokenDecimals
19507
+ );
19508
+ if (tokenComparison.wallet1.balanceRaw < tokenComparison.wallet2.balanceRaw) {
19509
+ analysis.push(
19510
+ `The failing wallet has less token balance (${tokenComparison.wallet1.balance}) than the working wallet (${tokenComparison.wallet2.balance}). Ensure sufficient balance for the transaction.`
19511
+ );
19512
+ }
19513
+ }
19514
+ if (analysis.length === 0) {
19515
+ analysis.push(
19516
+ "No obvious differences found between wallets. The issue may be related to contract-specific state (e.g., positions, allowances, whitelists) or transaction parameters."
19517
+ );
19518
+ }
19519
+ return {
19520
+ stateComparison,
19521
+ tokenComparison,
19522
+ analysis
19523
+ };
19524
+ }
19369
19525
  /*! Bundled license information:
19370
19526
 
19371
19527
  @noble/hashes/esm/utils.js:
@@ -19380,6 +19536,6 @@ async function uploadBlobViaPresign(params) {
19380
19536
  (*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
19381
19537
  */
19382
19538
 
19383
- export { DEFAULT_EXPIRES_IN_SEC, DEFAULT_MODE, VolrProvider, buildCall, buildCalls, createGetNetworkInfo, createPasskeyAdapter, defaultIdempotencyKey, normalizeHex, normalizeHexArray, uploadBlobViaPresign, useDepositListener, useInternalAuth, useMpcConnection, usePasskeyEnrollment, usePrecheck, useRelay, useVolr, useVolrAuthCallback, useVolrLogin, useVolrWallet };
19539
+ export { DEFAULT_EXPIRES_IN_SEC, DEFAULT_MODE, VolrProvider, analyzeContractForEIP7702, buildCall, buildCalls, compareERC20Balances, compareWalletStates, createGetNetworkInfo, createPasskeyAdapter, debugTransactionFailure, defaultIdempotencyKey, diagnoseTransactionFailure, getERC20Balance, getWalletState, isEIP7702Delegated, normalizeHex, normalizeHexArray, uploadBlobViaPresign, useDepositListener, useInternalAuth, useMpcConnection, usePasskeyEnrollment, usePrecheck, useRelay, useVolr, useVolrAuthCallback, useVolrLogin, useVolrWallet };
19384
19540
  //# sourceMappingURL=index.js.map
19385
19541
  //# sourceMappingURL=index.js.map