Skip to content

Conversation

@eranrund
Copy link

@eranrund eranrund commented Dec 18, 2025

Motivation

Hyperlane encountered a bundling issue with the Provable SDK due to its dependency on sync-request. One of sync-request’s transitive dependencies (sync-rpc) relies on legacy CommonJS require() syntax, which breaks Hyperlane’s ESM-based build:

node cli-bundle/index.js --version                               took  6s at  14:18:36
file:///Users/troykessler/work/hyperlane/hyperlane-monorepo/typescript/cli/cli-bundle/index.js:389077
    throw new Error(
          ^

Error: file:///Users/troykessler/work/hyperlane/hyperlane-monorepo/typescript/cli/cli-bundle/find-port.js:3
const getPort = require('get-port');
                ^

ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and '/Users/troykessler/work/hyperlane/hyperlane-monorepo/typescript/cli/cli-bundle/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
    at file:///Users/troykessler/work/hyperlane/hyperlane-monorepo/typescript/cli/cli-bundle/find-port.js:3:17
    at ModuleJob.run (node:internal/modules/esm/module_job:371:25)
    at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:702:26)
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:101:5)
@hyperlane-xyz/monorepo
└─┬ @hyperlane-xyz/[email protected] -> ./typescript/cli
  └─┬ @hyperlane-xyz/[email protected] -> ./typescript/aleo-sdk
    └─┬ @provablehq/[email protected]
      └─┬ [email protected] <- package only used in xml polyfill
        └─┬ [email protected] <- this package uses old commonjs require syntax which breaks on our side
          └── [email protected]

The SDK currently uses both:

  • xmlhttprequest-ssl
  • sync-request
    to polyfill XMLHttpRequest in Node.js.

This dual approach exists because the version of xmlhttprequest-ssl previously in use incorrectly decoded synchronous responses as UTF-8, corrupting binary data. To work around this, synchronous requests were routed through sync-request, which preserves raw bytes correctly.

However, newer versions of xmlhttprequest-ssl now handle response decoding properly, eliminating the need for sync-request entirely.

Note that sync requests are not desirable and long-term we should move away from that entirely, but that requires changes to snarkVM before the JS SDK can support that.

Test Plan

To verify this work I ran Hyperlane's test utility (https://github.com/troykessler/aleo-sdk-deploy) and was able to get it to work (with some minor changes).

I've also ran the aleo-multisig unit tests with this modified SDK and they passed.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR simplifies the XMLHttpRequest polyfill for Node.js by removing the dependency on sync-request and relying solely on xmlhttprequest-ssl v4.0.0. The change addresses a bundling issue in Hyperlane caused by legacy CommonJS syntax in sync-request's transitive dependencies, which broke ESM-based builds.

Key Changes:

  • Removed sync-request dependency from package.json
  • Upgraded xmlhttprequest-ssl from v3.1.0 to v4.0.0
  • Simplified XMLHttpRequest polyfill to use syncPolicy: "enabled" option instead of custom sync request handling

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
sdk/src/polyfill/xmlhttprequest.ts Replaced complex XMLHttpRequest class extension with simple factory function that enables synchronous requests via syncPolicy option
sdk/package.json Removed sync-request dependency and upgraded xmlhttprequest-ssl to v4.0.0

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}
} as any;
}
function XMLHttpRequest(opts?: any) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why was this refactored to no longer be a class?

Copy link
Author

Choose a reason for hiding this comment

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

Does it need to be a class? I believe this is working okay, and I think when I tried leaving it as a class it didn't work.
This might have to do with a change between xmlhttprequest-ssl 3.x and 4.x. In 3.x they were doing this:
https://github.com/mjwwit/node-XMLHttpRequest/blob/3.1.0/lib/XMLHttpRequest.js#L280
vs in 4.x:
https://github.com/mjwwit/node-XMLHttpRequest/blob/master/lib/XMLHttpRequest.js#L422

What is the issue with how it is currently done?

Copy link
Collaborator

Choose a reason for hiding this comment

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

It's not "wrong" per se, but... using functions as pseudo-classes is extremely old and outdated, it's not best practice and it's no longer recommended.

class is the modern standardized way to create classes, and class has various convenient features. So it's better to use it if we can.

This code should work...

globalThis.XMLHttpRequest = class extends $xmlhttprequest.XMLHttpRequest {};

...or possibly even this code...

globalThis.XMLHttpRequest = $xmlhttprequest.XMLHttpRequest;

Copy link
Author

Choose a reason for hiding this comment

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

Updated to using the class syntax.

Copy link
Collaborator

@Pauan Pauan 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, thanks!

@Pauan
Copy link
Collaborator

Pauan commented Dec 22, 2025

@eranrund By the way... the SDK works natively on Node, so I'm curious why you needed to patch some things to make it work. What version of Node are you using?

@eranrund
Copy link
Author

@eranrund By the way... the SDK works natively on Node, so I'm curious why you needed to patch some things to make it work. What version of Node are you using?

Please see the PR description - the stock SDK depends on sync-request, which uses an outdated javascript module system and it broke the build of one of Aleo's partners (Hyperlane).

It works fine on NodeJS but their build process failed due to the sync-request dependency. That package is also several years old and no longer maintained.

@Pauan
Copy link
Collaborator

Pauan commented Dec 22, 2025

Please see the PR description - the stock SDK depends on sync-request, which uses an outdated javascript module system and it broke the build of one of Aleo's partners (Hyperlane).

Yes, I know about that, but I'm referring to this:

https://github.com/troykessler/aleo-sdk-deploy/pull/1/files#diff-cd55066e51ef17ad8b88f13f571779227571ac127f85f9fea83ce78d1b033ddcR27-R35

It works fine on NodeJS but their build process failed due to the sync-request dependency. That package is also several years old and no longer maintained.

We test with various build systems, all of them can handle require, so I'm not sure what they're doing differently.

Also, sync-request is not the only dependency that uses require, so I'm not sure why they're having issues specifically with sync-request but not other packages.

@eranrund
Copy link
Author

Please see the PR description - the stock SDK depends on sync-request, which uses an outdated javascript module system and it broke the build of one of Aleo's partners (Hyperlane).

Yes, I know about that, but I'm referring to this:

https://github.com/troykessler/aleo-sdk-deploy/pull/1/files#diff-cd55066e51ef17ad8b88f13f571779227571ac127f85f9fea83ce78d1b033ddcR27-R35

It works fine on NodeJS but their build process failed due to the sync-request dependency. That package is also several years old and no longer maintained.

We test with various build systems, all of them can handle require, so I'm not sure what they're doing differently.

Also, sync-request is not the only dependency that uses require, so I'm not sure why they're having issues specifically with sync-request but not other packages.

To be honest, I am not super familiar with their build so I am not sure why they ran into this and others haven't.
I believe the patches I had to make to that script you linked to are because I am using file:../sdk/sdk to use my local SDK build, and I don't think this will be needed once the SDK is published and we are back to using a standard versioned dependency in package.json.

@Pauan
Copy link
Collaborator

Pauan commented Dec 23, 2025

Alright, understood. 👍

@iamalwaysuncomfortable iamalwaysuncomfortable changed the base branch from mainnet to feature/upgrade-xml-httprequest January 7, 2026 22:03
@iamalwaysuncomfortable iamalwaysuncomfortable merged commit 6bdab3e into ProvableHQ:feature/upgrade-xml-httprequest Jan 7, 2026
17 of 20 checks passed
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.

4 participants