Using @dfinity/agent in node.js

dfx identity --network ic get-principal leads to w2bwq-cyvg6...

in nodejs

const identity = initIdentity();

console.log(identity.getPrincipal().toText());

I get another value → cd5mb-c6i5a....

2 Likes

Are you sure your pem file is corresponding to a Secp256k1 key? and not Ed25519?

1 Like

I would say probably or yes because if I use the Ed25519KeyIdentity provider of agent-js instead of the Secp256k1KeyIdentity with the exact same code I get Error: bad secret key size

5 Likes

Yep same error for me.

Same here too
20chars

I’ve added reproductible identities across dfx and agent-js as an issue for SDK to resolve. It ought to work, and either a defect or lack of documentation is barring that functionality

3 Likes

Do you have a link to the issue?

We’ve shifted to Jira for our board to work with other teams at the foundation more easily, but I could also create an issue in agent-js to track it publicly

2 Likes

Hello dears, is there any update about reply #29 ?

Not that I know, I did not try again neither.

Yeah, that’s on me. I haven’t had the time to figure out what’s going on there

I’m also running into this issue as well

We’ve been investigating on and off for a while and haven’t been able to find a simple way to reproduce identities from dfx in agent-js. I think it’s going to require re-implementing the full logic of the Rust library that dfx uses as a new npm package.

It’s something we want to do, but it’s below a few other more critical features we want to get through first

It might be happening on tweetnacl, better using try catch and loop the keypair function

Update - @ericswanson helped me unblock this:

seed.txt

early cinnamon crucial teach mobile just toast real rebel around card priority spike aerobic result account marble hero action intact inside elbow wrestle oval

$ keysmith principal yields
bh66w-ffyze-maien-ejjje-wzhqi-crrjo-rcgs7-twjrh-kf2km-hbtia-eae

seed.js

const Identity = require("@dfinity/identity");
const hdkey = require("hdkey");
const fs = require("fs");

const { Secp256k1KeyIdentity } = Identity;

const bip39 = require("bip39");

const phrase = fs.readFileSync("seed.txt").toString().trim();

export const identityFromSeed = async (phrase) => {
  const seed = await bip39.mnemonicToSeed(phrase);
  const root = hdkey.fromMasterSeed(seed);
  const addrnode = root.derive("m/44'/223'/0'/0/0");

  return Secp256k1KeyIdentity.fromSecretKey(addrnode.privateKey);
};

identityFromSeed(phrase).then((identity) => {
  console.log(identity.getPrincipal().toString());
});

$ node seed.js yields
bh66w-ffyze-maien-ejjje-wzhqi-crrjo-rcgs7-twjrh-kf2km-hbtia-eae

We still have to hunt down the implementation used by rust-openssl/pkey.rs at master · sfackler/rust-openssl · GitHub, but this should open up the possibility to use a single identity across JS and dfx, from a shared seed phrase!

Of course, this comes with some security caveats -

  • Do not ever commit a seed phrase to your souce code.
  • THIS PATTERN SHOULD NEVER BE USED IN A FRONTEND APPLICATION
  • Use a different identity for each project to mitigate risk
  • Dfinity does not officially endorse doing this
7 Likes

This looks promising :partying_face:, would that also work for the pem file? since our dfx identity is created using a pem file, or is there a way to get the seed phrase from a pem file?

1 Like

also wondering this^

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