scrtlabs/secret.js

secret.js does not appear to have Secp256k1Pen

ChristianOConnor opened this issue · 3 comments

I am building a Secret NFT and I'm following this tutorial https://youtu.be/jRuSOos9ig4. I tried to deploy the NFT like this video narrator does around 31:12. I ran a the deploy-nft.js file which failed at this line:

const signingPen = await Secp256k1Pen.fromMnemonic(mnemonic).catch((err) => {
  throw new Error(`Could not get signing pen: ${err}`);
});

With this error:

TypeError: Cannot read properties of undefined (reading 'fromMnemonic')
    at main (C:\Users\nyusername\path\to\secret-nft-two\contract\deploy-nft.js:40:43)
    at Object.<anonymous> (C:\Users\nyusername\path\to\secret-nft-two\contract\deploy-nft.js:94:3)
    at Module._compile (node:internal/modules/cjs/loader:1105:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Module._load (node:internal/modules/cjs/loader:827:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
    at node:internal/main/run_main_module:17:47

I imported Secp256k1Pen at the top of the file like this:

const {
  EnigmaUtils,
  Secp256k1Pen,
  SigningCosmWasmClient,
  pubkeyToAddress,
  encodeSecp256k1Pubkey,
} = require("secretjs");

The entire file incorporating the above code looks like this:

const {
    EnigmaUtils,
    Secp256k1Pen,
    SigningCosmWasmClient,
    pubkeyToAddress,
    encodeSecp256k1Pubkey,
  } = require("secretjs");
  const fs = require("fs");
  
  // Load environment variables
  require("dotenv").config();
  
  const customFees = {
    upload: {
      amount: [{ amount: "5000000", denom: "uscrt" }],
      gas: "5000000",
    },
    init: {
      amount: [{ amount: "500000", denom: "uscrt" }],
      gas: "500000",
    },
    exec: {
      amount: [{ amount: "500000", denom: "uscrt" }],
      gas: "500000",
    },
    send: {
      amount: [{ amount: "80000", denom: "uscrt" }],
      gas: "80000",
    },
  };
  
  const main = async () => {
    const httpUrl = process.env.__VITE_SECRET_REST_URL;
  
    // Use key created in tutorial #2
    const mnemonic = process.env.VITE_MNEMONIC;
  
    // A pen is the most basic tool you can think of for signing.
    // This wraps a single keypair and allows for signing.
    const signingPen = await Secp256k1Pen.fromMnemonic(mnemonic).catch((err) => {
      throw new Error(`Could not get signing pen: ${err}`);
    });
  
    // Get the public key
    const pubkey = encodeSecp256k1Pubkey(signingPen.pubkey);
  
    // get the wallet address
    const accAddress = pubkeyToAddress(pubkey, "secret");

    // 1. Initialize client
    const txEncryptionSeed = EnigmaUtils.GenerateNewSeed();

    const client = new SigningCosmWasmClient(
        httpUrl,
        accAddress,
        (signBytes) => signingPen.sign(signBytes),
        txEncryptionSeed, customFees,
    );
    console.log(`Wallet address=${accAddress}`);
  
    // 2. Upload the contract wasm
    const wasm = fs.readFileSync('my-snip721/contract.wasm');
    console.log('Uploading contract');
    const uploadReceipt = await client.upload(wasm, {})
        .catch((err) => { throw new Error(`Could not upload contract: ${err}`); });

    // Get the code ID from the receipt
    const { codeId } = uploadReceipt;
    const initMsg = {
        /// name of token contract
        name: process.env.CONTRACT_NAME,
        /// token contract symbol
        symbol: process.env.CONTACT_SYMBOL,
        /// entropy used for prng seed
        entropy: process.env.RANDOM_LOWERCASE_LETTERS_SEED,
        /// optional privacy configuration for the contract
        config: {
            public_owner: true
        },
    }
    const contract = await client
      .instantiate(
        codeId,
        initMsg,
        `My Snip721${Math.ceil(Math.random() * 10000)}`
      )
      .catch((err) => {
        throw new Error(`Could not instantiate contract: ${err}`);
      });
    const { contractAddress } = contract;
    console.log("contract: ", contract, "address:", contractAddress);
  };
  
  main().catch((err) => {
    console.error(err);
  });

And I run this file with node deploy-nft.js. Also according to my package.json file, I'm using "secretjs": "^1.6.13"

So why is it failing with this error? Is secret.js not properly exposing Secp256k1Pen?

Hi, this looks to be a very old secret.js code. Please read the current docs at https://github.com/scrtlabs/secret.js#readme, you can use Wallet to import your mnemonics.

Hi, this looks to be a very old secret.js code. Please read the current docs at https://github.com/scrtlabs/secret.js#readme, you can use Wallet to import your mnemonics.

Gotcha, I actually modified my code but I'm getting a new problem. I am trying to upload a build of this contract https://github.com/baedrik/snip721-reference-impl. I made this new upload script which I reassembled from this code: https://github.com/scrtlabs/SecretJS-Templates/blob/master/5_contracts/main.js. It looks like this:

const { Wallet, SecretNetworkClient } = require("secretjs");
const fs = require("fs");

// Load environment variables
require("dotenv").config();

const main = async () => {
  const wallet = new Wallet(process.env.VITE_MNEMONIC);

  // Create a connection to Secret Network node
  // Pass in a wallet that can sign transactions
  // Docs: https://github.com/scrtlabs/secret.js#secretnetworkclient
  const secretjs = new SecretNetworkClient({
    url: process.env.__VITE_SECRET_REST_URL,
    wallet: wallet,
    walletAddress: wallet.address,
    chainId: process.env.VITE_SECRET_CHAIN_ID,
  });
  console.log(`Wallet address=${wallet.address}`);

  // 2. Upload the contract wasm
  const wasm = fs.readFileSync('my-snip721/contract.wasm');
  console.log('Uploading contract');

  const tx = await secretjs.tx.compute.storeCode(
    {
      sender: wallet.address,
      wasm_byte_code: wasm,
      source: "https://github.com/baedrik/snip721-reference-impl",
      builder: "baedrik",
    },
    {
      gasLimit: 1_000_000,
    }
  );
  console.log(tx);

  const codeId = Number(
    tx.arrayLog.find((log) => log.type === "message" && log.key === "code_id")
      .value
  );
  console.log("codeId: ", codeId);

  // contract hash, useful for contract composition
  const contractCodeHash = (await secretjs.query.compute.codeHashByCodeId({code_id: codeId})).code_hash;
  console.log(`Contract hash: ${contractCodeHash}`);
};

main();

I get this error:

TypeError: Cannot read properties of undefined (reading 'find')

Notice that I'm logging tx which looks like this after I format it to json:

{
    "height": 0,
    "timestamp": "",
    "transactionHash": "LONG STRING HERE...",
    "code": 18,
    "codespace": "sdk",
    "info": "",
    "tx": {
        "@type": "/cosmos.tx.v1beta1.Tx",
        "body": {
            "messages": ["Array"],
            "memo": "",
            "timeout_height": "0",
            "extension_options": [],
            "non_critical_extension_options": []
        },
        "auth_info": { "signer_infos": ["Array"], "fee": ["Object"] },
        "signatures": [
            "ANOTHER LONG STRING HERE..."
        ]
    },
    "rawLog": "builder invalid: invalid request",
    "jsonLog": "undefined",
    "arrayLog": "undefined",
    "events": [],
    "data": [],
    "gasUsed": 822,
    "gasWanted": 0,
    "ibcResponses": []
}

arrayLog is undefined. So how do I get this snip 721 to upload?

If tx.code != 0 then the tx failed, then in rawLog you can see that you get the error builder invalid: invalid request. I think the builder field should be a docker image version, so maybe it's getting the wrong format? You can also just not pass this field