Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(payment-processor): load hinkal lib asyncronously #1573

Merged
merged 3 commits into from
Feb 21, 2025

Conversation

alexandre-abrioux
Copy link
Member

@alexandre-abrioux alexandre-abrioux commented Feb 18, 2025

Context

The Request Network library is relatively heavy to load from a front-end point of view, more especially the payment-processor package. Here are some stats for a front-end that includes packages needed for payment, and built with Vite.js:

> ls -lh build/assets/@requestnetwork/
total 7,3M
308K currency-BI28kHzu.js
128K data-format-CF2Ej1ak.js
1,2M payment-detection-B7AW9tt1.js
5,7M payment-processor-COb8hmRF.js
1    smart-contracts-l0sNRNKZ.js
1    types-l0sNRNKZ.js

Changes

In this PR, I introduce a quick optimization that would reduce the payment-processor load time and resolve a CSP warning for non-Hinkal users.

  • @hinkal/common represents a large amount of the final code for the payment-processor package after transpilation. It could be loaded asynchronously to lighten frontend bundles. The picture below is a visualization of the space taken by each sub-dependency of the payment-processor package, according to /~https://github.com/btd/rollup-plugin-visualizer.

  • @hinkal/common depends on libsodium (also quite heavy, see below) which runs WASM code in the browser. Loading this lib is incompatible with a Content-Security-Policy that does not allow script-src 'wasm-unsafe-eval'. For builders that do not use the Hinkal integration, it does not make sense to relax the CSP header to silence such a warning. Loading Hinkal only on-demand would not trigger such warnings for non-Hinkal users. Related: Chrome requires unsafe-eval to run webassembly code jedisct1/libsodium.js#196

image

Summary by CodeRabbit

  • Refactor
    • Enhanced the processing of token payments by introducing improved asynchronous handling. This update ensures that all transaction details are fully resolved before proceeding, which leads to more reliable and consistent payment experiences for users.

Copy link
Contributor

coderabbitai bot commented Feb 18, 2025

Walkthrough

The changes primarily modify the erc-20-private-payment-hinkal.ts file in the payment processor package. The modifications include reordering of imports, separating the ERC20__factory import, and updating two functions to be asynchronous. The asynchronous modifications involve updating the function signatures and adding await where dynamic imports (like emporiumOp) are used. Overall, the changes adjust the control flow by ensuring asynchronous operations complete before the functions return.

Changes

File Path Change Summary
packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts - Reordered ethers imports with BigNumber and BigNumberish prioritized.
- Moved ERC20__factory import to a separate line.
- Updated prepareErc20ProxyPaymentFromHinkalShieldedAddress and prepareErc20FeeProxyPaymentFromHinkalShieldedAddress to be asynchronous with the addition of await for dynamic imports.

Sequence Diagram(s)

sequenceDiagram
    participant C as Client Code
    participant P as Payment Module
    participant E as EmporiumOp Module

    C->>P: Call prepareErc20ProxyPaymentFromHinkalShieldedAddress(...)
    P->>E: Await dynamic import of emporiumOp
    E-->>P: Return emporiumOp module
    P-->>C: Return Promise resolving to IPreparedPrivateTransaction

    C->>P: Call prepareErc20FeeProxyPaymentFromHinkalShieldedAddress(...)
    P->>E: Await dynamic import of emporiumOp
    E-->>P: Return emporiumOp module
    P-->>C: Return Promise resolving to IPreparedPrivateTransaction
Loading

Suggested reviewers

  • MantisClone
  • leoslr
  • sstefdev
  • aimensahnoun
✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@alexandre-abrioux alexandre-abrioux changed the title chore: load hinkal lib asyncronously chore(payment-processor): load hinkal lib asyncronously Feb 18, 2025
@alexandre-abrioux alexandre-abrioux marked this pull request as ready for review February 18, 2025 14:36
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts (2)

131-134: Update function documentation to reflect async nature.

The functions have been correctly made async to support dynamic imports. Consider updating the JSDoc comments to indicate that these functions now return Promises.

 /**
  * Prepare the transaction to privately pay a request through the ERC20 proxy contract, can be used with a Multisig contract.
  * @param request request to pay
  * @param amount optionally, the amount to pay. Defaults to remaining amount of the request.
+ * @returns Promise<IPreparedPrivateTransaction>
  */

Also applies to: 173-177


148-148: Optimize dynamic imports to avoid duplication.

The dynamic import of emporiumOp is duplicated across both functions. Consider extracting it to a shared utility function to improve code maintainability and reduce duplicate code.

+async function getEmporiumOp() {
+  const { emporiumOp } = await import('@hinkal/common');
+  return emporiumOp;
+}

 export async function prepareErc20ProxyPaymentFromHinkalShieldedAddress(
   request: ClientTypes.IRequestData,
   amount?: BigNumberish,
 ): Promise<IPreparedPrivateTransaction> {
   // ...
-  const { emporiumOp } = await import('@hinkal/common');
+  const emporiumOp = await getEmporiumOp();
   // ...
 }

 export async function prepareErc20FeeProxyPaymentFromHinkalShieldedAddress(
   request: ClientTypes.IRequestData,
   amount?: BigNumberish,
   feeAmountOverride?: BigNumberish,
 ): Promise<IPreparedPrivateTransaction> {
   // ...
-  const { emporiumOp } = await import('@hinkal/common');
+  const emporiumOp = await getEmporiumOp();
   // ...
 }

Also applies to: 193-193

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bae9bfd and e31f685.

📒 Files selected for processing (1)
  • packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts (7 hunks)
🧰 Additional context used
🧠 Learnings (1)
packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts (2)
Learnt from: MantisClone
PR: RequestNetwork/requestNetwork#1482
File: packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts:80-99
Timestamp: 2024-12-09T18:59:04.613Z
Learning: In the `RequestNetwork` codebase, payment processor functions such as `payErc20ProxyRequestFromHinkalShieldedAddress` in `packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts` should not include explicit request validation or try/catch blocks, and should rely on the underlying components (like `hinkalObject`) to handle error reporting.
Learnt from: MantisClone
PR: RequestNetwork/requestNetwork#1482
File: packages/payment-processor/test/payment/erc-20-private-payment-hinkal.test.ts:0-0
Timestamp: 2024-12-04T05:05:19.610Z
Learning: The function `createRequestForHinkal` in `erc-20-private-payment-hinkal.test.ts` is intended for testing purposes only and should remain in the test directory.
🔇 Additional comments (2)
packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts (2)

1-1: LGTM! Import optimization improves bundle size.

The separation of type imports from value imports enables better tree-shaking and async loading capabilities.

Also applies to: 22-22


88-89:

✅ Verification successful

Verify all callers handle async prepare functions.

The changes correctly await the prepare functions. However, we should verify that all other callers of these functions in the codebase are updated to handle the async nature.

Also applies to: 115-116


🏁 Script executed:

#!/bin/bash
# Search for all usages of the prepare functions to ensure they're properly awaited
rg "prepareErc20(Fee)?ProxyPaymentFromHinkalShieldedAddress" -A 2 -B 2

Length of output: 2351


Async Callers Verified – Code Update Approved

The changes in packages/payment-processor/src/payment/erc-20-private-payment-hinkal.ts correctly use await for both prepareErc20ProxyPaymentFromHinkalShieldedAddress (lines 88-89) and prepareErc20FeeProxyPaymentFromHinkalShieldedAddress (lines 115-116). The grep results confirm that all current usages within the file properly await the async prepare functions.

Please ensure that any future callers also correctly handle the async returns.

Copy link
Member

@MantisClone MantisClone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me 🙆

As a result of these changes, the hinkal functions for preparing transactions are now asynchronous. I consider this to be a non-breaking change because I assume most users of this code would use the pay... functions rather than the prepare... functions.

Thank you also for cleaning up the import ordering to make it alphabetical.

@MantisClone
Copy link
Member

I'm sad to see that one of Hinkal's sub-dependencies is incompatible with a Content-Security-Policy that does not allow script-src 'wasm-unsafe-eval'. I forwarded this analysis to the Hinkal team.

@alexandre-abrioux
Copy link
Member Author

alexandre-abrioux commented Feb 19, 2025

I haven't tested the Hinkal integration, but it might be fine even without allowing wasm-unsafe-eval in your CSP. My guess is that you would get a warning in the browser console, but the underlying crypto library (libsodium) would switch to a Javascript fallback. Again, that is just a guess by reading through this: jedisct1/libsodium.js#196 ; some are still having issues, but as far as I understand, the topic is closed on the libsodium side. It might be worth a try!

@nkoreli
Copy link
Contributor

nkoreli commented Feb 19, 2025

Hi @alexandre-abrioux and @yomarion,

Another dependency in @hinkal/common is snarkjs, which relies on wasm-unsafe-eval. Snarkjs is widely used in zero-knowledge proof applications like Railgun and Penumbra, primarily because it enables in-browser proving.

The WASM files used by snarkjs are generated by CIRCOM (https://docs.circom.io/), a toolkit for zk-circuits. Using WASM for client-side proving offers significant performance improvements over JavaScript.

Since we are in the process of integrating with Request Finance, do you think it might be possible to adjust the content policy to permit wasm-unsafe-eval?

@alexandre-abrioux
Copy link
Member Author

alexandre-abrioux commented Feb 20, 2025

@nkoreli Thank you for all the details 🙏 At the moment, Request Finance does not require Wasm scripts, so we do not allow it. We can of course reassess during implementation (but let's discuss it internally as this is a security topic).

@MantisClone MantisClone merged commit a5dbaa0 into master Feb 21, 2025
11 checks passed
@MantisClone MantisClone deleted the hinkal-async branch February 21, 2025 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants