How to use bitcoin -rpcwallet flag in deno RPC - javascript

I want to create an address in a wallet with bitcoin-cli, the command for this will look like this for the loaded wallet bitcoin-cli getnewaddress some_users and with Deno I can just do
import { createRemote } from "https://deno.land/x/gentleRpc/rpcClient.ts";
let Node = new URL("http://127.0.0.1:8332");
Node.port = "8332";
Node.username = "some_user";
Node.password = "some_password";
const remote = createRemote(Node);
const address = remote.getnewaddress(addressLabel);
I would love to know how to use deno rpc for cases where I need to specify the -rpcwallet flag, like this bitcoin-cli -rpcwallet=some_unique_wallet getnewaddress some_users

So after reading the doc further, I realised I can do this by passing the wallet name to the url like this http://127.0.0.1:8332/wallet/${walletName} or just this http://127.0.0.1:8332/wallet/ for the default wallet.
So the code will look like this,
createConnection(walletName?: string) {
const uri = !!walletName ?
'http://127.0.0.1:8332/wallet/${walletName}' :
'http://127.0.0.1:8332/wallet/';
let Node = new URL(uri);
Node.port = "8332";
Node.username = "some_user";
Node.password = "some_password";
return createRemote(Node);
}

Related

How can I get transactions from a wallet using alchemy websockets

I want to get all new transactions from a specified wallet and Im using this code. It just dont work when I use the function tx["transaction"]["from"] and I filter the wallet or ca I want on "WALLET".
Im using Alchemy methods with ws and I have read the documentation about how to use it, I should be missing something.
const { Alchemy, Network, AlchemySubscription } = require("alchemy-sdk")
const {ethers, FixedNumber} = require("ethers")
const delay = require('delay')
require("dotenv").config()
const ARBI_WS_KEY = process.env.ARBI_WS_KEY
const settings = {
apiKey: ARBI_WS_KEY, // Replace with your Alchemy API Key
network: Network.ARB_MAINNET, // Replace with your network
}
const alchemy = new Alchemy(settings)
// Subscription for Alchemy's minedTransactions API
const add = async () => {
alchemy.ws.on(
{
method: AlchemySubscription.MINED_TRANSACTIONS,
},
(tx) => {
let add0 = String(tx["transaction"]["from"])
if( add0 == "WALLET"){
console.log(tx["transaction"]["hash"])
}
}
)
}
Its weird because everything works when I filter tx["transaction"]["to"] and I specify a wallet or a contract to filter but when trying to filter "from" I dont get anything.

Delete image from url Firebase Storage

In my cloud functions, I'm trying to delete an image based on its url, but I think that I don't use correctly the API as I'm getting errors :
const admin = require('firebase-admin');
exports.deleteImageWhenOfferDeleted = functions.firestore
.document('offers/{offerId}')
.onDelete(async(snap, context) => {
console.log('----------------start function--------------------')
const deletedOffer = snap.data();
var imageUrlToDelete = deletedOffer.imageUrl;
await admin.storage.getPathStorageFromUrl(imageUrlToDelete).delete();
function getPathStorageFromUrl(url){
const baseUrl = "https://firebasestorage.googleapis.com/v0/b/muslim-coloc.appspot.com/o/";
let imagePath = url.replace(baseUrl,"");
const indexOfEndPath = imagePath.indexOf("?");
imagePath = imagePath.substring(0,indexOfEndPath);
imagePath = imagePath.replace("%2F","/");
return imagePath;
}
I think you're missing brackets after storage word.
You need to get an instance of storage object.
admin.storage.getReferenceFromUrl(...)
should be
admin.storage().getReferenceFromUrl(...)
BTW: Consider using TypeScript, because it catches errors like that during compilation.

hdwallet provider create wallet for user

I have created a smart contract that facilitates a token sale. I want a user to be able to press a button that automatically generates an ERC20 wallet that tokens can be sent to.
I am using the truffle HDWallet Provider and Infura. I don't want the user to have to use MetaMask or anything else. I will sign the transactions on the backend using the private key of the user's generated wallet.
How would I go about implementing this so a new wallet is created for every new user that wants to perform a transaction?
This is the code that allowed me to create a wallet on a button press. I now need to find a way to store the credentials of these wallets so I can sign transactions and transfer tokens to them.
var bip39 = require('bip39');
const EthereumUtil = require('ethereumjs-util');
const hdkey = require('hdkey');
const mnemonic = bip39.generateMnemonic(); //generates string
const seed = bip39.mnemonicToSeed(mnemonic); //creates seed buffer
const root = hdkey.fromMasterSeed(seed);
const masterPrivateKey = root.privateKey.toString('hex');
const addrNode = root.derive("m/44'/60'/0'/0/0");
const pubKey = EthereumUtil.privateToPublic(addrNode._privateKey);
const addr = EthereumUtil.publicToAddress(pubKey).toString('hex');
const address = EthereumUtil.toChecksumAddress(addr);
Its pretty simple, just create a HDWalletProvider and the provider.addresses has all the accounts you can use:
Here is the code:
const createWallet = function(_providerUrl) {
const mnemonicPhrase = bip39.generateMnemonic()
let provider = new HDWalletProvider({
mnemonic: {
phrase: mnemonicPhrase
},
providerOrUrl: "http://localhost:8545"
});
return provider.addresses
}
Addresses has the accounts
The solution has already been commented above, but I have a better suggestion for you. I think it's better to generate only one mnemonic in your backend and you create infinite accounts from that mnemonic. From each account you extract the private key and store it, store the address of the account and the index of the account.
Management code:
const HDWalletProvider = require("#truffle/hdwallet-provider");
const Web3 = require("web3");
const mnemonicPhrase = "mnemonicPhrase here";
const urlRPC = "https://bsc-dataseed.binance.org";
//Creating another instance to query balances
const Web3Instance = require('web3');
const web3instance = new Web3Instance(new Web3Instance.providers.HttpProvider(urlRPC));
//HD Wallet Provider loads by default only 10 accounts
//We change the limit to as many accounts as we want
//You cannot run the loop below for i greater than 10, because for
const limit = 50;
async function getAccount() {
provider = new HDWalletProvider({
mnemonic: mnemonicPhrase,
numberOfAddresses: limit,
providerOrUrl: urlRPC,
addressIndex: 0,
});
//HDWalletProvider is compatible with Web3
//Use it at Web3 constructor, just like any other Web3 Provider
const web3 = new Web3(provider);
//I realized that iterating a loop to limit always gives an error when it reaches limit
//This happens in this HD Wallet Provider package
//limit - 1 seems to work best
for (let i = 0; i < limit - 1; i ++) {
var get = await web3.eth.getAccounts()
var address = get[i];
var balanceETH = await web3instance.eth.getBalance(address)
//Checking the adress
console.log(address);
console.log(balanceETH);
}
}
getAccount();
Here is more information:
https://ethereum.stackexchange.com/questions/52370/web3-create-account-from-mnemonic-passphrase/144340#144340

BCH transaction failed: Missing inputs 25

I am using Bitcoin Cash JS to create a transaction, and my code is as follows:
let BITBOXCli = require('bitbox-cli/lib/bitbox-cli').default;
const explorers = require('bitcore-explorers')
const insight = new explorers.Insight('https://test-bch-insight.bitpay.com')
let BITBOX = new BITBOXCli();
let txb = new BITBOX.TransactionBuilder('testnet');
var To = 'mkiuwbSQQVxMvvbBcYEKUdZgJfURhu3hrW'
var from = 'mvStb7hPtDCL8dmyifPGcYTuToVzf7ajTb';
var bch = require('bitcoincashjs')
var bchLib = require('#owstack/bch-lib')
const buf = new Buffer('b27ab45d3e3d157e8b95f800347974f9991cf13ceb814e1992f40c5e4e6d5253', 'hex')
const privateKey = new bch.PrivateKey(buf, bch.Networks.testnet)
const address = privateKey.toAddress('testnet')
insight.getUnspentUtxos(address.toString(), function (error, utxos) {
if (error) {
console.error(error)
return
}
console.log(utxos)
const utxo = {
txid: utxos[0].txid,
outputIndex: utxos[0].vout,
script: utxos[0].scriptPubKey,
satoshis: utxos[0].satoshis
}
const transaction = new bch.Transaction()
.from(utxo)
.to(To, 50000)
.sign(0, privateKey)
console.log(transaction.toString())
});
Now when I am running this code, I am able to get the raw transaction hash but I am not able to broadcast transaction and message is as follows:
Missing Inputs Error:-25
Any idea about this error?
Or is there any other way to create BCH transaction?
It looks like you're trying to create a simple transaction to send BCH from one address to another. There is now an example for this exact use case in the BITBOX SDK repository:
https://github.com/Bitcoin-com/bitbox-javascript-sdk/blob/master/examples/applications/wallet/send-bch/send-bch.js
There are also other examples there like creating a wallet checking a balance:
https://github.com/Bitcoin-com/bitbox-javascript-sdk/tree/master/examples/applications/wallet
There are even more examples in the Wormhole SDK. (Wormhole SDK is a superset of BITBOX, so it can do anything BITBOX can do):
https://github.com/Bitcoin-com/wormhole-sdk/tree/master/examples

Verify PKCS#7 (PEM) signature / unpack data in node.js

I get a PKCS#7 crypto package from a 3rd party system.
The package is not compressed and not encrypted, PEM-encoded, signed with X.509 certificate.
I also have a PEM cert file from the provider.
The data inside is XML
I need to do the following in Node.JS:
extract the data
verify the signature
A sample package (no sensitive info, data refers to our qa system) http://pastebin.com/7ay7F99e
OK, finally got it.
First of all, PKCS messages are complex structures binary-encoded using ASN1.
Second, they can be serialized to binary files (DER encoding) or text PEM files using Base64 encoding.
Third, PKCS#7 format specifies several package types from which my is called Signed Data. These formats are distinguished by OBJECT IDENTIFIER value in the beginning of the ASN1 object (1st element of the wrapper sequence) — you can go to http://lapo.it/asn1js/ and paste the package text for the fully parsed structure.
Next, we need to parse the package (Base64 -> ASN1 -> some object representation). Unfortunately, there's no npm package for that. I found quite a good project forge that is not published to npm registry (though npm-compatible). It parsed PEM format but the resulting tree is quite an unpleasant thing to traverse. Based on their Encrypted Data and Enveloped Data implementations I created partial implementation of Signed Data in my own fork. UPD: my pull request was later merged to the forge project.
Now finally we have the whole thing parsed.
At that point I found a great (and probably the only on the whole web) explanative article on signed PKCS#7 verification: http://qistoph.blogspot.com/2012/01/manual-verify-pkcs7-signed-data-with.html
I was able to extract and successfully decode the signature from the file, but the hash inside was different from the data's hash. God bless Chris who explained what actually happens.
The data signing process is 2-step:
original content's hash is calculated
a set of "Authorized Attributes" is constructed including: type of the data singed, signing time and data hash
Then the set from step 2 is signed using the signer's private key.
Due to PKCS#7 specifics this set of attributes is stored inside of the context-specific constructed type (class=0x80, type=0) but should be signed and validated as normal SET (class=0, type=17).
As Chris mentions (https://stackoverflow.com/a/16154756/108533) this only verifies that the attributes in the package are valid. We should also validate the actual data hash against the digest attribute.
So finally here's a code doing validation (cert.pem is a certificate file that the provider sent me, package is a PEM-encoded message I got from them over HTTP POST):
var fs = require('fs');
var crypto = require('crypto');
var forge = require('forge');
var pkcs7 = forge.pkcs7;
var asn1 = forge.asn1;
var oids = forge.pki.oids;
var folder = '/a/path/to/files/';
var pkg = fs.readFileSync(folder + 'package').toString();
var cert = fs.readFileSync(folder + 'cert.pem').toString();
var res = true;
try {
var msg = pkcs7.messageFromPem(pkg);
var attrs = msg.rawCapture.authenticatedAttributes;
var set = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, attrs);
var buf = Buffer.from(asn1.toDer(set).data, 'binary');
var sig = msg.rawCapture.signature;
var v = crypto.createVerify('RSA-SHA1');
v.update(buf);
if (!v.verify(cert, sig)) {
console.log('Wrong authorized attributes!');
res = false;
}
var h = crypto.createHash('SHA1');
var data = msg.rawCapture.content.value[0].value[0].value;
h.update(data);
var attrDigest = null;
for (var i = 0, l = attrs.length; i < l; ++i) {
if (asn1.derToOid(attrs[i].value[0].value) === oids.messageDigest) {
attrDigest = attrs[i].value[1].value[0].value;
}
}
var dataDigest = h.digest();
if (dataDigest !== attrDigest) {
console.log('Wrong content digest');
res = false;
}
}
catch (_e) {
console.dir(_e);
res = false;
}
if (res) {
console.log("It's OK");
}
Your answer is a big step in the right direction. You are however missing out an essential part of the validation!
You should verify the hash of the data against the digest contained in the signed attributes. Otherwise it would be possible for someone to replace the content with malicious data. Try for example validating the following 'package' with your code (and have a look at the content): http://pastebin.com/kaZ2XQQc
I'm not much of a NodeJS developer (this is actually my first try :p), but here's a suggestion to help you get started.
var fs = require('fs');
var crypto = require('crypto');
var pkcs7 = require('./js/pkcs7'); // forge from my own fork
var asn1 = require('./js/asn1');
var folder = '';
var pkg = fs.readFileSync(folder + 'package').toString();
var cert = fs.readFileSync(folder + 'cert.pem').toString();
try {
var msg = pkcs7.messageFromPem(pkg);
var attrs = msg.rawCapture.authenticatedAttributes; // got the list of auth attrs
var set = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, attrs); // packed them inside of the SET object
var buf = new Buffer(asn1.toDer(set).data, 'binary'); // DO NOT forget 'binary', otherwise it tries to interpret bytes as UTF-8 chars
var sig = msg.rawCapture.signature;
var shasum = crypto.createHash('sha1'); // better be based on msg.rawCapture.digestAlgorithms
shasum.update(msg.rawCapture.content.value[0].value[0].value);
for(var n in attrs) {
var attrib = attrs[n].value;
var attrib_type = attrib[0].value;
var attrib_value = attrib[1].value[0].value;
if(attrib_type == "\x2a\x86\x48\x86\xf7\x0d\x01\x09\x04") { // better would be to use the OID (1.2.840.113549.1.9.4)
if(shasum.digest('binary') == attrib_value) {
console.log('hash matches');
var v = crypto.createVerify('RSA-SHA1');
v.update(buf);
console.log(v.verify(cert, sig)); // -> should type true
} else {
console.log('hash mismatch');
}
}
}
}
catch (_e) {
console.dir(_e);
}
based on inspiration form this answer, I've implemented a sample for signing and verifying pdf files using node-signpdf and node-forge.

Categories