Giter VIP home page Giter VIP logo

js-cardano-wasm's Introduction

DEPRECATED

These libraries are no longer compatible with Cardano since the 29th July 2020 Hardfork. The whole serialisation format has been redefined. Transactions are no longer the same either.

cardano wasm binding for JavaScript

Installation

# install rustup
curl https://sh.rustup.rs -sSf | sh
# use nightly version
rustup install nightly-2018-06-05
rustup target add wasm32-unknown-unknown --toolchain nightly

Build the Library

To Compile the rust crypto to a Web Assembly (WASM) module and build JS library run the ./build script. (only necessary if you want to build locally)

Run the Example

There is a simple example application in js-example that can be run to test some of the features.

installation

within js-example/ folder

  1. npm install
  2. npm run install

Building

within js-example/ run npm run build

Running

open js-example/index.html in any browser

Use the Crypto Library

Install

You can either build the library locally on your machine to test the latest version with your project or install via NPM.

Install locally:

in the root of this repo: npm link in the root of your project: npm link rust-cardano-crypto

Install via NPM:

in the root of your project: npm install rust-cardano-crypto

Import the API in Your Code

// Import like this:
import CardanoCrypto from 'rust-cardano-crypto'
// Or access as global in browsers:
CardanoCrypto.PaperWallet.scramble(iv, password, input)

Notes

The rust code contains rwc/ a fork of rust-crypto without the dependencies that cannot be build easily in a wasm environment, and minus the algorithms that are not useful.

js-cardano-wasm's People

Contributors

alanverbner avatar ddeath avatar dominikguzei avatar nicarq avatar nicolasdp avatar ntfreem avatar rooooooooob avatar sebastiengllmt avatar vincenthz avatar vsubhuman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

js-cardano-wasm's Issues

Is there anyway to retrieve Daedalus master key from Daedalus memo?

Hi, I have Daedalus memo and I want to get master key from these memo to contact with Yoroi/wasp (for few reasons). Is there any method to get master key? I have use below method to get Daedalus master key, then put it on Yoroi to test but it can't retrieve my address:

const cardano = require('cardano-wallet');
const dMemo = ...;
const dEntropy = cardano.Entropy.from_english_mnemonics(dMemo);
const dWallet = cardano.DaedalusWallet.recover(dEntropy);
const privateKey = cardano.PrivateKey.new(dEntropy);
const pk = privateKey.to_hex();
console.log("pk", pk);

or

const addressToCheck = ...;
const dChecker = cardano.DaedalusAddressChecker.new(dWallet);
const toRustAddr = cardano.Address.from_base58(addressToCheck);
const checkedAddr = dChecker.check_address(toRustAddr);
if (checkedAddr.is_checked()) {
    console.log("pk", checkedAddr.private_key().to_hex());
}

Thanks so much for help.

broken package.json for cardano-wallet

package.json in cardano-wallet npm module is missing the "main" key, so no pointing to the js file resulting in Error: Cannot find module 'cardano-wallet' when importing the npm module.

It should also be transpiled, since it's using new syntax. I'm assuming something went wrong during build process.

wasm for cardano-wallet-browser isn't built for browser (probably)

If you installed cardano-wasm-browser from npm and tried to load it with a page you will get

Failed to load module script: The server responded with a non-JavaScript MIME type of "application/wasm". Strict MIME type checking is enforced for module scripts per HTML spec.

The most popular case - is when wasm-file was built for server-use but browser.

Add to_byte() method

Would be great to have a method similar to to_hex() or to_json() for the transaction, as it can be used to send the raw bytes right to the submit-api. Something like this:
pub fn to_bytes(&self) -> Result<String, JsValue> { let bytes = cbor!(&self.0).map_err(|e| JsValue::from_str(&format! {"{:?}", e}))?; Ok(bytes) }

Paper Wallet API inconsistency

Old API

takes a mnemonic, turns it into an entropy [u8] internally and uses that for paperwallet:unscramble

unscramble(module, iconv.encode(password, 'utf8'), Bip39.mnemonicToEntropy(mnenomics))

let output = paperwallet::unscramble(&pass[..], &input[..]);

New API

takes the entropy directly as a [u8]

pub fn paper_wallet_unscramble(paper: &[u8], password: &str) -> Result<Entropy, JsValue> {

Problem

However, we have no way of turning type Entropy to [u8] in Yoroi as Entropy only exposes two methods: from_english_mnemonics and to_english_mnemonics.

This seems like a strange quirk in the API because of the following:

paper_wallet_scramble input: Entropy
paper_wallet_scramble output: [u8]
paper_wallet_unscramble input: [u8]
paper_wallet_unscramble output: Entropy

This allows you to write the following code

    let bytes = paper_wallet_scramble(&test.entropy, &test.iv, test.password).unwrap();
    let bytes: Vec<u8> = JsValue::into_serde(&bytes).unwrap();
    let entropy = paper_wallet_unscramble(&bytes, test.password).unwrap();

However, in Yoroi we don't unscramble right after scrambling. These are done in different sessions. Maybe it makes more sense to have it consistently use Entropy for all these methods? We can also fix it with something like #57 but then we should probably also add a from_array function also which is a bit more complex (which is why it was left as a TODO

/// TODO: interface to generate a new entropy
)

"RuntimeError: unreachable" when creating a new TxOut

I'm trying to build a transaction with the Tx object and when I try to add a new output:

let tx = Tx.create();
tx = Tx.addOutput(tx, Tx.newTxOut('Ae2tdPwUPEZ8d5Q2MEbU7tfGL9pF73A7zDb4ippdWPmKWseDPrh7GTYBvpo', 10));

I receive this error:

UnhandledPromiseRejectionWarning: RuntimeError: unreachable
    at wasm-function[197]:3358
    at wasm-function[250]:258
    at wasm-function[362]:153
    at wasm-function[428]:136
    at wasm-function[22]:833
    at exports.newTxOut (/home/user/NodeJS/project/node_modules/rust-cardano-crypto/dist/index.js:11711:26)
    at Object.args [as newTxOut] (/home/user/NodeJS/project/node_modules/rust-cardano-crypto/dist/index.js:2313:84)

I'm using Node 8.14.0 and rust-cardano-crypto ver 0.2.0
I also tried manually building from this repository with the same result.

Input seem to work just fine, the error is thrown only when trying to add a new output.

How to connect to Byron

Hi,

I am developing a simple, albeit custom Cardano wallet using NodeJS + Typescript. As advised by @SebastienGllmt I decided to use js-cardano-wasm to integrate with blockchain. For starters, I'd like to integrate with Byron testnet.

How do I connect to Byron instead of mainnet? Following your cardano-wallet example there is that BlockchainSettings class with its mainnet method. Digging through an implementation it seems this method provides ProtocolMagic with some arbitrary value (7648240731) which, I presume, represents mainnet. That's some magic indeed!

I'd imagine I need to use from_json method of BlockchainSettings to connect to Byron instead. Can I get some info on how to do this?

Thanks,
KSS

TypeError: account_public.bip44_chain is not a function

`const Cardano = require("cardano-wallet");

const MNEMONICS = "job unit evolve when convince scale again leisure october knee inject awful";
const PASSWORD = "thisispassword";

// to connect the wallet to mainnet
let settings = Cardano.BlockchainSettings.mainnet();

// recover the entropy
let entropy = Cardano.Entropy.from_english_mnemonics(MNEMONICS);
// recover the wallet
let wallet = Cardano.Bip44RootPrivateKey.recover(entropy, PASSWORD);

// create a wallet account
let account = wallet.bip44_account(Cardano.AccountIndex.new(0 | 0x80000000));
let account_public = account.public();

// create an address
let chain_pub = account_public.bip44_chain(false);
let key_pub = chain_pub.address_key(Cardano.AddressKeyIndex.new(0));
let address = key_pub.bootstrap_era_address(settings);

console.log("Address m/bip44/ada/'0/0/0", address.to_base58());
`

{ code: 'InvalidContent', message: 'Invalid witness' }

When i submit signed transaction i got error

{ code: 'InvalidContent', message: 'Invalid witness' }``

`const Wallet = require('cardano-wallet');
const axios = require('axios');

(async () => {

const MNEMONICS = "bottom stone xxxx xxxx xxx xxxx tourist finish xxx trend xxx xxxxxx";
let settings = Wallet.BlockchainSettings.mainnet();

let entropy = Wallet.Entropy.from_english_mnemonics(MNEMONICS);
let wallet = Wallet.Bip44RootPrivateKey.recover(entropy);

let account = wallet.bip44_account(Wallet.AccountIndex.new(0 | 0x80000000));
let account_public = account.public();

let chain_prv = account.bip44_chain(false);
let key_prv = chain_prv.address_key(Wallet.AddressKeyIndex.new(0));
// console.log('address public ' + key_prv.to_hex());
let chain_pub = account_public.bip44_chain(false);
let key_pub = chain_pub.address_key(Wallet.AddressKeyIndex.new(0));
// console.log('address public ' + key_pub.to_hex());

let address = key_pub.bootstrap_era_address(settings);

console.log("Address m/bip44/ada/'0/0/0", address.to_base58());

// Building a transaction

let transaction_builder = new Wallet.TransactionBuilder();

let trx = await axios.get('https://cardanoexplorer.com/api/addresses/summary/Ae2tdPwUPEZKfa3EfkEhj9K1jyxUhkuxYaG1SAVFyD3KzrfLBgwaRV11zc1');
// console.log('Inputs:', trx.data.Right.caTxList[0].ctbInputs,'\nOutputs:',trx.data.Right.caTxList[0].ctbOutputs, '\nInputs Total:', trx.data.Right.caTxList[0].ctbInputSum.getCoin/1000000);

console.log(trx.data.Right.caTxList.length)

var trxResult = [];

for (let i = 0; i < trx.data.Right.caTxList.length; i++) {
    // console.log(trx.data.Right.caTxList[i].ctbId);
    trxResult.push(trx.data.Right.caTxList[i].ctbId);
}
// console.log(trxResult);

const inputs = [
    // { pointer: { id: inputResult[2], index: 2 }, value: 1 },
    // { pointer: { id: inputResult[1], index: 1 }, value: 1 },
    { pointer: { id: trxResult[0], index: 0 }, value: 5 }
];
// console.log(inputs);

const outputs = [
    // TODO: you can test the balance by changing the value here.
    { address: "Ae2tdPwUPEZCNHvZbqWhKmeHPxzvZxrnwJZghsm16Vjrzd8DriLn9jCarpr", value: "1000000" }
];

for (let index = 0; index < inputs.length; index++) {
    const pointer = Wallet.TxoPointer.from_json(inputs[index].pointer);
    const value = Wallet.Coin.from(inputs[index].value, 0);
    transaction_builder.add_input(pointer, value);
}

console.log("all inputs set...", transaction_builder.get_input_total().to_str());

for (let index = 0; index < outputs.length; index++) {
    const txout = Wallet.TxOut.from_json(outputs[index]);
    transaction_builder.add_output(txout);
}

console.log("all outputs set...", transaction_builder.get_output_total().to_str());

// verify the balance and the fees:
const fee_algorithm = Wallet.LinearFeeAlgorithm.default();
const balance = transaction_builder.get_balance(fee_algorithm);
if (balance.is_negative()) {
    console.error("not enough inputs, ", balance.value().to_str());
    throw Error("Not enough inputs");
} else {
    if (balance.is_zero()) {
        console.info("Perfect balance no dust", balance.value().to_str());
    } else {
        console.warn("Loosing some coins in extra fees: ", balance.value().to_str());
    }
}

let transaction = transaction_builder.make_transaction();

// console.log("unsigned transaction built", transaction);

let transaction_finalizer = new Wallet.TransactionFinalized(transaction);

// console.log("transaction finalizer built", transaction_finalizer);

for (let index = 0; index < inputs.length; index++) {
    const witness = Wallet.Witness.new_extended_key(
        settings,
        key_prv,
        transaction_finalizer.id()
    );
    transaction_finalizer.add_witness(witness);
    console.log("signature ", index, "added");

}

// at this stage the transaction is ready to be sent
const signed_transaction = transaction_finalizer.finalize();
console.log("ready to send transaction: ", signed_transaction.to_hex());

const result = signed_transaction.to_json()
console.log(result.tx);
// console.log(result.witness);

})();`

Output:-

Address m/bip44/ada/'0/0/0 Ae2tdPwUPEZKfa3EfkEhj9K1jyxUhkuxYaG1SAVFyD3KzrfLBgwaRV11zc1
all inputs set... 5.000000
all outputs set... 1.000000
Loosing some coins in extra fees: 3.834159
signature 0 added
ready to send transaction: 82839f8200d818582482582050a89fc4d468c5b25022faa0d01b33ad6551c3f71fee10fe5dd5fcd860a6831900ff9f8282d818582183581c9bf3a0807b668107a9cac1e50e10ada427b7e68835de69f46ad104efa0001adcb4a5531a000f4240ffa0818200d8185885825840d9f10d0ad1e60ca23de9918b7e1cd6b27d3efe564166b428dda5203a076aa83f08a74cb34468ae6b256c71e295d773d79bbd3d6f5b78044652dfb2768744a3bb5840d739b94a8951e95e0524866c44e88991898f16bfd733d23590f7f177f11c23b3097f0993128c3a1273d5864eb7a62b4cc9ff3a33ce0791d66dcada7dd5bda409
{ inputs:
[ { id:
'50a89fc4d468c5b25022faa0d01b33ad6551c3f71fee10fe5dd5fcd860a68319',
index: 0 } ],
outputs:
[ { address:
'Ae2tdPwUPEZCNHvZbqWhKmeHPxzvZxrnwJZghsm16Vjrzd8DriLn9jCarpr',
value: 1000000 } ] }

then i push signed transaction on mainnet:

`
const axios = require('axios');

const signedBody = {
signedTx: Buffer.from('82839f8200d818582482582050a89fc4d468c5b25022faa0d01b33ad6551c3f71fee10fe5dd5fcd860a6831900ff9f8282d818582183581c9bf3a0807b668107a9cac1e50e10ada427b7e68835de69f46ad104efa0001adcb4a5531a000f4240ffa0818200d8185885825840d9f10d0ad1e60ca23de9918b7e1cd6b27d3efe564166b428dda5203a076aa83f08a74cb34468ae6b256c71e295d773d79bbd3d6f5b78044652dfb2768744a3bb5840d739b94a8951e95e0524866c44e88991898f16bfd733d23590f7f177f11c23b3097f0993128c3a1273d5864eb7a62b4cc9ff3a33ce0791d66dcada7dd5bda409', 'hex').toString('base64'),
}

// Send a POST request
axios({
method: 'post',
url: 'https://explorer2.adalite.io/api/v2/txs/signed',
data: JSON.stringify(signedBody),
headers: {
'Content-Type': 'application/json; charset=utf-8',
},
}).then(function (response) {
console.log(response);
}).catch(function (error) {
console.log(error);
});`

Give Error:-

data: { code: 'InvalidContent', message: 'Invalid witness' } } }

Mnemonic is converted to seed differently than in Daedalus

I found out that when I run index.html after building everything as suggested in the readme, the generated seed does not correspond with the seed generated by Daedalus (cardano-sl) for the same mnemonic. Is that a deliberate choice? Because that implies that your implementation would produce a totally different lineage of wallets for the same mnemonic than Daedalus does currently. Otherwise the root key derivation seems to be the same. I give an example below:

Let's take the mnemonic
'scissors basket lunch wasp index gather runway nerve portion angry priority senior'

I found out that Daedalus generates for this mnemonic the seed:
5820c0bffab455cf86117cff257de97ff333586e0922e38c220e21f00f2591e7aaad

On the other hand, your code generates the following seed:
f20485724b951bcd154e53bea20104f2636b37503a54441f01ea3c0033e1af9a

It seems like Daedalus before performing the blake2b256 hash encodes the BIP39 entropy to CBOR and the output of the hash function as well before generating the keypair

(look at the "toHashSeed" function here: https://github.com/input-output-hk/cardano-sl/blob/0b85142eede30cac8e1c5e627785d523f7ee8432/wallet/src/Pos/Util/BackupPhrase.hs and "createKeypairFromSeed" here: https://github.com/input-output-hk/cardano-sl/blob/05bea127ac698bd8737d88c69e51de02ae3c2c17/crypto/Pos/Crypto/Signing/Signing.hs)

, but your implementation takes the entropy as a string (the output of bip39.mnemonicToEntropy) and puts it directly into the blake2b256 function ("mnemonicToSeedImpl" function here: https://github.com/input-output-hk/js-cardano-wasm/blob/13132f770970e45d1ae2773f599e44ebb2339a40/js-example/src/Components/Bindings/BIP39.js). If you need more clarifications, feel free to ask and I will try to provide a more detailed explanation. Of course I admit that I can be missing something or that I got something wrong when analyzing the outputs of both implementations.

[npm cardano-wallet] era of node and transaction do not match

I'm making nodejs application and running cardano stack.

  1. cardano-node (1.18.0)
  2. cardano-submit-api (2.1.0)

I did this test and got raw transaction
when i push this transaction to cardano-submit-api, I got
"The era of the node and the tx do not match. The node is running in the Shelley era, but the transaction is for the Byron era."
error.

I think this is because of shelly hard fork
How can I make complete transaction?
Or any recent javascript library?

What is module param in the method?

export const publicKeyToAddress = (module, xpub, payload) => {
  const bufxpub    = newArray(module, xpub);
  const bufpayload = newArray(module, payload);
  const bufaddr    = newArray0(module, 1024);

  let rs = module.wallet_public_to_address(bufxpub, bufpayload, payload.length, bufaddr);
  let addr = copyArray(module, bufaddr, rs);

  module.dealloc(bufaddr);
  module.dealloc(bufpayload);
  module.dealloc(bufxpub);

  return addr;
};

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.