Trying to test Wallet instantiation in Solana JS - javascript

I'm trying to follow some code to test out instantiating a wallet in code. I'm hardcoding private key (will not do this in prod obviously) just to see how everything works. I'm getting this error:
throw new Error('bad secret key size');
^
Error: bad secret key size
My code is as below:
import { Connection, Keypair, Transaction } from '#solana/web3.js'
import fetch from 'cross-fetch'
import { Wallet } from '#project-serum/anchor'
import bs58 from 'bs58'
const connection = new Connection('https://ssc-dao.genesysgo.net')
const PRIVATE_KEY = 'my secret key is this very dumb long confusing and unnecessary string'
const wallet = new Wallet(Keypair.fromSecretKey(bs58.decode(process.env.PRIVATE_KEY || '')))

I suspect it's either:
PRIVATE_KEY is not loaded properly: your code is missing require("dotenv").config(); at the top.
PRIVATE_KEY is not in the right format in your .env file: from where and how did you export it? Are you sure it's base58 encoded?

So the issue here was the encoding. For ease of use, it's best to use the phantom wallet. I tried converting the seed to bs58 but I was still unsuccessful. If you insist on using another wallet and are using the .js web3 library for Solana, you'd probably be better off using
const wallet = new Wallet(Keypair.fromSecretKey(new Uint8Array([1,2,3,4,5,6])))
but this would require you to keep your private key array exposed which is not recommended.

Related

How can I ensure browser compatibility for the webcrypto API in Typescript?

So, what I'm trying to achieve is to use the Webcrypto API in Typescript and compile it to Javascript code that runs in the browser.
In the Browser, accessing the Webcrypto API is simple. Just window.crypto or crypto for short.
In node.js, you have to import it from the built-in "crypto" library first:
import { webcrypto as crypto } from "crypto"
Since I want to run it in the browser, I don't have to and also can not import it.
And here is the problem: For Typescript, I have to import the node library to get the necessary types. If I don't, this is the error:
src/main.ts:15:43 - error TS2503: Cannot find namespace 'crypto'.
So, for Typescript to compile, I have to import "crypto", but for the browser to run it I must not.
Possible work-arounds I can think of are:
tell Typescript that "crypto" (window.crypto) exists and is equivalent to crypto.webcrypto from the node library
tell Typescript to not include the line with the import in the output Javascript file
tell the browser to ignore that import
None of those I could find in the internet.
What I also tried is to use a dynamic import so I can conditionally import it, something like:
let _crypto: any = window?.crypto
if (!_crypto) {
_crypto = await import("crypto")
}
const crypto: any = _crypto
In theory, this should make the browser just ignore that "crypto" import since window.crypto exists.
But Typescript doesn't import the necessary types for dynamic imports for some reason.
In case this is needed, this is part of my code:
export function sign(privkey: crypto.CryptoKey, data: any) {
data = YSON.stringify(data)
data = new TextEncoder().encode(data).buffer
return crypto.subtle.sign({name: "ECDSA", hash: {name: "SHA-256"}}, privkey, data)
}
This function takes some data, stringifies it, and signs it using a private key.
The Y in YSON is intended.
The error is in the first line of that code snippet, I'm using the crypto.CryptoKey type.

Executing code pre and post mutation graphql neo4j apollo server

I'm just getting started with GraphQL and I've worked mostly with featherjs to build REST APIs so far. There's the concept of hooks to run code before or after interacting with a service. I wanted to know if there's a way to achieve something similar in a graphql setup.
The specific stack I'm using is neo4j and graphql, express, and apollo server. Since neo4j has a graphql module, I'm not writing the general queries and mutations, just the model types.
For a concrete example, below is a basic API server. It's put together using docker compose and has users and applications. I would like to in general be able to run arbitrary code before or after a mutation with access to the model being modified. Things like more complex validation before, or side effects after.
Those things could be here, for example, before changing the state of an application to declined, make sure that a note is added. Or after changing the state to approved, send an email to the applicant.
I'm not sure how or where to implement this kind of thing, any help is appreciated! Or also if I'm thinking about graphql wrong and there's a better way of doing what I'm trying to do.
Thanks!
import http from 'http';
import express from 'express';
import neo4j from 'neo4j-driver';
import {Neo4jGraphQL} from '#neo4j/graphql';
import {gql, ApolloServer} from 'apollo-server-express';
import {ApolloServerPluginDrainHttpServer} from 'apollo-server-core';
const typeDefs=gql`
type User {
email: String!
applications: [Application!] #relationship(type: "APPLICANT", direction: OUT)
}
type Application {
user: User! #relationship(type: "APPLICANT", direction: IN)
state: String!
note: String
}
`;
const driver=neo4j.driver(
'neo4j://neo4j:7687',
neo4j.auth.basic('neo4j', 'password')
);
const {schema}=new Neo4jGraphQL({typeDefs, driver});
(async ()=>{
const app=express();
const server=http.createServer(app);
const apollo=new ApolloServer({
schema,
plugins: [ApolloServerPluginDrainHttpServer({httpServer: server})]
});
await apollo.start();
apollo.applyMiddleware({app});
await new Promise(r=>server.listen({port: 4000}, r));
console.log('GraphQL server listening at '+apollo.graphqlPath);
})();

How to import a library into a web worker in React.js?

I am trying to run a face detection process in the background of my React app using a web worker. I am using a library called face-api.js to do the face detection. But I'm unsure as to how to import this library to use in my worker.js file.
worker.js
import * as faceapi from 'face-api.js';
this.onmessage = (e) => {
console.log("Message from worker.js");
this.postMessage('Hello Main')
};
TestComponent.js
import React, {useEffect} from 'react'
function TestComponent() {
useEffect(() => {
const worker = new Worker('./workers/worker.js')
worker.postMessage('Hello Worker')
worker.onmessage = e => {
console.log('Message received from worker:', e.data)
}
}
);
return (
<div>
<h1> Test Component </h1>
</div>
)
}
export default TestComponent
I run this test code and I get the following error on chrome:
/workers/worker.js:1 Uncaught SyntaxError: Cannot use import statement outside a module
I have tried using require to import the library which didn't work. I also tried declaring the worker as a module
const worker = new Worker('./workers/worker.js', type: "module")
This makes the error go away but then nothing works: the worker does not do what it is intended to do.
Please point me in the right direction. Thanks in advance!
I guess you should use importScript() in your service worker file
you need to use {type:"module"} in the options of worker constructor for use "import" features in the worker file.
https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker
options Optional
An object containing option properties that can be set when creating the object instance. Available properties are as follows:
type: A DOMString specifying the type of worker to create. The value can be classic or module. If not specified, the default used is classic.
credentials: A DOMString specifying the type of credentials to use for the worker. The value can be omit, same-origin, or include. If not specified, or if type is classic, the default used is omit (no credentials required).
name: A DOMString specifying an identifying name for the DedicatedWorkerGlobalScope representing the scope of the worker, which is mainly useful for debugging purposes.

Discord.js - module export doesnt work anymore

So I used the module export for my TOKEN to make index.js look cleaner, so my index.js looked like that:
const TOKEN = m.TOKEN;
and my config.js (where my TOKEN was stored) looked like that:
const TOKEN = '<token>';
exports.TOKEN = TOKEN;
I accidentally deleted my index.js and re-did it, but now it doesnt work anymore. I always get the error "An invalid token was provided.". What did I do wrong?
Although it's much more common to use a JSON file to hold plain values, you can work with modules as shown in the setup below.
config.js:
exports.TOKEN = 'abcd1234';
index.js:
const { TOKEN } = require('./config.js'); // path may vary
{ TOKEN } is part of the destructuring syntax. require() returns the target module's exports property, which in this case, is an object; you can extract the property you need and use it later.

Nodejs crypto in typescript file

I have created my own hash.js file that requires crypto and exports two functions that use crypto. It works fine in my api.js file when I hash passwords. However Now I am trying to import this file in my user.service.ts file so that I can send the hashed version of the password as a query parameter instead of the password itself. When I try to do so I always get a TypeScript error telling me that the functions crypto uses are not functions. However I can still console log the object I import and it looks legit to me. I looked at other java script files in the node_modules folder and I cannot see anything that should be wrong with my file.
I have also found out that there seems to be some definition file that I need to create but I have also had many attempts at creating such a file but nothing seems to work
A few hours of googling and the lack of knowledge amongst lack of time on this project led me to this post, it is my first stackoverflow post and I hope that it is not to unclear and I am glad to provide any information needed to help me resolve this issue.
Error code from console
LoginComponent.html:18 ERROR TypeError: crypto.randomBytes is not a function
at Object.genRandomString (hash.js:12)
at UserService.loginUser (user.service.ts:82)
at LoginComponent.getUser (login.component.ts:54)
at LoginComponent.onSubmit (login.component.ts:44)
at Object.eval [as handleEvent] (LoginComponent.html:18)
at handleEvent (core.es5.js:12014)
at callWithDebugContext (core.es5.js:13475)
at Object.debugHandleEvent [as handleEvent] (core.es5.js:13063)
at dispatchEvent (core.es5.js:8607)
at core.es5.js:10775
LoginComponent.html:18 ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 31, nodeDef: {…}, elDef: {…}, elView: {…}}
the hash.js file
'use strict';
var crypto = require('crypto');
/**
* generates random string of characters i.e salt
* #function
* #param {number} length - Length of the random string.
*/
function genRandomString (length){
return crypto.randomBytes(Math.ceil(length/2))
.toString('hex') /** convert to hexadecimal format */
.slice(0,length); /** return required number of characters */
};
/**
* hash password with sha512.
* #function
* #param {string} password - List of required fields.
* #param {string} salt - Data to be validated.
*/
function sha512(password, salt){
var hash = crypto.createHmac('sha512', salt); /** Hashing algorithm sha512 */
hash.update(password);
var value = hash.digest('hex');
return {
salt:salt,
passwordHash:value
};
};
module.exports = {
genRandomString: genRandomString,
sha512: sha512
};
There seems to be some confusion mixing JavaScript and TypeScript, but since I came across this issue myself, here is how I solved it.
First, your hash.js file should be hash.ts. Then you can import crypto and use it normally. Related code below:
import * as crypto from "crypto";
public setEncryptionKeyDES(sKey: string) {
const desIV = Buffer.alloc(8);
this.encLobby.cipher = crypto.createCipheriv(
"des-cbc",
Buffer.from(sKey, "hex"),
desIV,
);
this.encLobby.cipher.setAutoPadding(false);
this.encLobby.decipher = crypto.createDecipheriv(
"des-cbc",
Buffer.from(sKey, "hex"),
desIV,
);
this.encLobby.decipher.setAutoPadding(false);
this.isSetupComplete = true;
}
Edit1: Adding #attdona's answer from below, make sure you install #types/node into your project as well, or you will receive many errors related to node modules not being found.
Just hitted this issue (node v13.12.0, tsc v3.8.3). In my case the import:
import * as crypto from "crypto";
gives the error:
error TS2307: Cannot find module 'crypto'
because I have to install types definition for node: it includes crypto ambient declarations.
npm install #types/node
Note: If you have a global install of #types/node then you have to explicitly declare the path where #types
are located with --typesRoot option.
See here for details.
When I try to do so I always get a TypeScript error telling me that the functions crypto uses are not functions.
This is happening because TypeScript statically analyzes your files and tries to help you with types of data that you're working with. If you're using a function written in JavaScript without any hint to TypeScript about what this function is using as arguments and what is the type of its return value, it simply cannot do its job, which is why you're getting an error.
You could create a decalration file, but you do not need to if you want a quick fix and if you won't be using these raw JS functions in other files. You just need to declare it anywhere in the file. You can read more about using declare keyword in TypeScript.
However I can still console log the object I import and it looks legit to me.
Judging by your screenshot, the function randomBytes is called properly (as you can see from the stack trace printed below the error). The problem is that the crypto object does not contain a method named randomBytes. This is because crypto is a global object in newer browsers.
Your crypto.js file is probably assuming existence of a different crypto global object than what browser has. Either provide this object in the proper scope so your function can see it, or inline those functions using a bundler such as Rollup.
Well this turned out to be a rather horrific rabbit hole to go down. I followed a bunch of recommended suggestions but ultimately the solution that worked for me was (as always...) super-simple, ONCE you know how.
The answer was to use the browser built-in crypto functionality. I only wanted to check a one-way digest of a password as being sufficient for a very lightweight app. However most guides were only partial suggestions, or didn't work with my app's setup of using Angular 7 and babel. So here's the final code I ended up with, with the following notes:
Need to encode into an array buffer to perform the digest
The digest function is returning a promise, so had to unwrap its value using .then
Did not require adding any NPM modules or imports
Anyway here's the code, hope it helps other Stack Overflowers.
I also found Daniel Roesler's Github page very useful for implementations of various web cryptography examples.
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-user-create',
templateUrl: './user-create.component.html',
styleUrls: ['./user-create.component.css']
})
export class UserCreateComponent implements OnInit {
constructor() { }
ngOnInit() {
sha256("hello").then(digestValue => {
console.log(digestValue);
});
}
}
async function sha256(str) {
const encoder = new TextEncoder();
const encdata = encoder.encode(str);
const buf = await crypto.subtle.digest("SHA-256", encdata);
return Array.prototype.map.call(new Uint8Array(buf), x=>(('00'+x.toString(16)).slice(-2))).join('');
}

Categories