Issue in Next with NPM Package "Cannot set property crypto of #<Window> which only has getter"

I'm working in Next.js and not sure if that's where the problem is coming from, but I'm just trying to import the NPM package, and am receiving this error immeadietly:

"TypeError: Cannot set property crypto of # which has only a getter"

Can anyone point me in the right direction to get the package working? Thank you so much,

1 Like

Hey @tsmoreau, what package are you referring to here?

Just the standard Defender Relay Client from here:

I was thinking I could use the API POST method described in there if I couldn't get the NPM defender package working, but I couldn't find the docs for that.

For the import method, I'm literally just pasting in:

import { Relayer } from 'defender-relay-client';
const relayer = new Relayer({apiKey: API_KEY, apiSecret: API_SECRET});

with the API keys replaced of course, but I'm getting the error immediately on import there, not even trying to do anything with it.

I can link a codesandbox that has the error live, if that helps.

That'll definitely help, since this seems to be related to the build configuration.

https://jpws1.sse.codesandbox.io/yggcodes

That's the page that has the error live. The IDE end of the sandbox is here:

I don't have any special webpack build settings setup at all. Just the defaults. I saw another issue a user had with Next.js integration and an aws package, but I managed to get around that one.

Please let me know if there's anything else I can provide to help point me in the right direction, as I was really hoping for a simple integration on this one :laughing:

I'm also getting the same error trying the simplest of import methods with just a standard Next.js create-app, so I'm not sure what's going on.

It might be Nextjs related. Any help at all would much appreciated. Is there any chance the HTTP API method is still available?

The even simpler build displaying the error:

Well, if anyone does figure out what's going on with webpack and next.js that's making the Defender NPM package fail in even the simplest of builds with just create-next-app, please let me know.

I'm quite sure other folks have managed to get this working, and even just a link to a working example would be very nice.

@tsmoreau the issue is that the defender-relay-client package is meant to be used on node.js backends, not browser-based environments. Including the relay-client in your frontend forces you to expose your API keys, which give control over your Relayer to whoever holds them - which you definitely want to avoid.

If you want to trigger a transaction from your frontend, the suggested way to go is to hit a backend that runs the relay-client and checks whether the caller is authorized to fire that tx. Many teams use Autotasks with a webhook for this, or you can use your own serverless function.

1 Like

Thank you so much @spalladino I really appreciate the help, I'm still getting my head around next.js quirks and believe I understand your suggestions! I'll give it a go implementing it via webhooks and a serverless function. Many thanks again, it's much appreciated!

1 Like

I'm getting this problem also in Next.js. I don't use the code anywhere browser-side, but I think just the fact that this attempt to assign to global.crypto during import causes the app to crash. If I wrap it in a check for browser vs non-browser context, everything works:

if (typeof window === 'undefined') {
    global.crypto = require('crypto');
}

I made a PR that illustrates this fix: https://github.com/OpenZeppelin/defender-client/pull/187

In JavaScript, the majority of elements are objects, with the notable exceptions of null and undefined. When attempting to access an undefined variable, it invariably returns 'undefined,' and you cannot retrieve or modify any properties of an undefined object. This scenario triggers the "Uncaught TypeError: cannot set property of undefined." To mitigate this issue, it's crucial to ensure variable initialization, particularly in situations where initialization is missing. Furthermore, adhering to best practices, you should verify the values of variables for null or undefined before utilizing them. If you only need to ascertain whether a value exists, you can use an 'if' statement, and if you're uncertain about a variable's existence, use the 'typeof' operator to check it, like so:

if (value) {
  // Perform an action
}

if (typeof some_variable !== "undefined" && some_variable !== null) {
  // Manage the value
}