Using @dfinity/agent in node.js

What am I missing here? I used this pattern in my node.js script, and the identity actually works fine. The problem is that when I try to include my actor from /src/declaration/project_name/project_name.js or /src/declaration/project_name/index.js I get the dreaded: SyntaxError: Unexpected token ‘export’ or Cannot use import statement outside a module. I can get around this by copying the export const idlFacotry…line from the file into my script and getting rid of the export. But this is really annoying to do every time. Perhaps I’ve missed some updates to the js world in the last couple of years, but I’ve tried a number of things and I either get that something isn’t compatible with commonjs or visa versa. Does the IDL get dumped somewhere that I can reference with a require(‘x’) statement?

1 Like

If you are using NodeJS LTS or more recent versions you can use script module files .mjs.

What I do is adding a postbuild script in package.json that automatically copy the .did.js files to .did.mjs files. Then in myscript.mjs script I can import the idlFactory as following (modules script support import)

import {idlFactory} from '..dfx/local/canisters/manager/manager.did.mjs';

Got a couple of scripts there GitHub - papyrs/ic: Backend canisters and providers of Papyrs

1 Like

Just to confirm… I want to use my default dfx identity to authenticate with my canister using the @dfinity/agent library in node…

Ideally using the PEM file in ~/.config/dfx/identity/default/identity.pem. I’m guessing from this thread that this is not possible right now? (I need to create a new identity / principal using keysmith and use that instead. Does that sound right?)

1 Like

I think you can use Key Smith to produce a back up phrase for your default identity. Just run the help for key Smith and you’ll see a number of options.

1 Like

If I do this I have to convert all of my other require statements to import statements correct? I feel like I tried this but one of my existing packages demanded that I use require or something like that. I’ll give this a try and report back.

Yes probably, a bit a pity but at least a one time change. Let me know if it works out :crossed_fingers:

Thanks to everyone above for the great commentary, really was nice to follow as I started troubleshooting not being able to load in my existing dfx principal via agent-js (I received the same different dfx and node principals as everyone else).

Since it did take me a bit of time to get through it all, hopefully these steps make it easier for those of you running into a similar issue (as of the time of this post).

Steps

  1. Navigate to my .dfx identities → ~/.config/.dfx/identity
  2. Create a new identity → mkdir local-testing; cd local-testing
  3. Download quill since keysmith is now deprecated.
  4. Test that quill is installed correctly → quill
  5. Look up how to generate a key → quill generate --help
  6. Generate a key and seed file → quill generate --pem-file identity.pem --seed-file seed.txt
  7. Now implement Kyle’s code snippet below (copied from comment this post is replying to)
  1. If you run this an have NodeJS version 17+, you will receive the following error coming from the hdkey library import → Error: error:0308010C:digital envelope routines::unsupported. The possible solutions for getting around this are here, the easiest of which is downgrading to node 16. (@kpeacock/sdk team can you provide a node 17+ solution? :slightly_smiling_face: )
  2. Now running the above node script and dfx identity get-principal should return the same identity! Yay!
4 Likes

So there’s no way to just pass in a path to a PEM file and get an identity that can be used in @dfinity/agent? It used to be the case that I could just pass in JSON object and all of this worked, that was last Summer. What happened?

a JSON object has always worked and still does work. The complicated flow is specifically for deriving an identical principal across dfx, quill, and agent-js

Do you know where the documentation is on what the JSON object should look like? I keep getting errors with it

Here is working code:

6 Likes

It does work! Thank you!

1 Like

For all those who are interested on this thread, I have created a dfinity module in BlueprintJS called blueprint-dfinity. The goal of this module is to make it easier to write NodeJS clients for the Internet Computer.

Some of the key features of this BlueprintJS module are:

  • Declarative approach for defining actors
  • Ability to bind actors and their source canisters to properties
  • Codifies bootstrapping code

The current version of trunk uses the original property definition approach to defining actors, and binding them to object properties. The newest version of the blueprint-dfinity, which is to be released with v5, uses decorators to define the actors and bindings to properties on ES6 classes.

blueprint/packages/blueprint-dfinity at v5 · onehilltech/blueprint · GitHub

Please have a look and provide feedback.

Disclaimer. I am the creator of BlueprintJS.

4 Likes

Heads up to anyone who’s still viewing this thread:

In September the sdk (DFX) changed from generating Ed25519 identities to Secp256k1 identities.

feat: secp256k1 keys (#2499) · dfinity/sdk@4f10e12 · GitHub, which was included in 0.12.0-beta.2, and then eventually released with 0.12.0, (see the documentation site release notes)

For example, if I go back to DFX < 0.12.0, generate an identity with dfx identity new <alias>, this solution will work, but if one uses any newer versions of dfx that uses different key generation, it will break.

@AdamS @kpeacock Are there any node based solutions in agent-js or elsewhere for pulling in the new Secp256k1 identities from a dfx >=0.12.0 generated pem file?

Also I tried playing with the blueprint solution provided by the post directly above this one :point_up: , but upon testing it with identities generated by dfx >= 0.12.0 I’ve found @hilljh82’s solution now produces a different identity (maybe it worked previously but there were a few changes made?).

In case this helps, when I was trying to verify public keys they had to be converted to DER format first.

Here is the code with both Ed25519 and Secp256k1 identities support mops/pem.js at master · ZenVoich/mops · GitHub (the previous link was to an old commit)

2 Likes

This is my current recommendation - use a seed phrase in node.js and dfx. Internet Computer Content Validation Bootstrap

You can drop the seed phrase in seed.txt (which should always be gitignored), and the import it with dfx identity import --seed-file ./seed.txt

1 Like

@kpeacock

Is there an issue with the Ed25519 and/or Secp256k1 solutions provided by ZenVoich?

Several developers I’ve spoken with prefer for the solution that imports the dfx generated pem file instead of the quill generated seed.txt (which they’ve professed the seed.txt derived identity import feels like a “hacky”, “roundabout”, or “unstable” solution).

It’s also about consistency, mostly because then developers are using two different tools to manage identity/canisters.

there’s nothing wrong with using the PEM files - we just haven’t added official support or documentation for it yet.

instead of the quill generated seed.txt (which they’ve professed the seed.txt derived identity import feels like a “hacky”, “roundabout”, or “unstable” solution).

Quill is unnecessary, unless you’re trying to use an existing PEM file in a seed phrase context. I simply suggest using a freshly generated seed phrase from your tool of choice, which will work nicely in CI contexts

1 Like