Skip to content
This repository has been archived by the owner on Dec 12, 2023. It is now read-only.

Address generation should use a mnemonic #49

Open
Thoralf-M opened this issue Sep 6, 2021 · 10 comments
Open

Address generation should use a mnemonic #49

Thoralf-M opened this issue Sep 6, 2021 · 10 comments
Labels
enhancement New feature or request

Comments

@Thoralf-M
Copy link
Member

Description

When a snapshot is generated the address for it should be derived from a mnemonic.

Motivation

Will be much easier to use because people can use Firefly, wallet.rs or any client library to send the funds, that's not possible with the private key alone.

Requirements

  1. Generate address using a mnemonic
  2. Store the mnemonic so the user can access it

Open questions (optional)

Instead of generating a random mnemonic, maybe the default should be the same?
If the one from here would be used one doesn't need to generate anything and if it's by default the same one can just send this one if someone has issues finding it.

Are you planning to do it yourself in a pull request?

No.

@jmcanterafonseca-iota jmcanterafonseca-iota added the enhancement New feature or request label Sep 24, 2021
@Thoralf-M
Copy link
Member Author

In the meantime this script can be used with iota.js

// tsc .\index.ts --lib "es2018, dom"; node index.js
import {
    Bech32Helper,
    Ed25519Address,
    ED25519_ADDRESS_TYPE,
    IKeyPair,
    ISigLockedSingleOutput,
    IUTXOInput,
    sendAdvanced,
    SIG_LOCKED_SINGLE_OUTPUT_TYPE,
    SingleNodeClient,
    UTXO_INPUT_TYPE
} from "@iota/iota.js";
import { Converter } from "@iota/util.js";

async function run() {
    const client = new SingleNodeClient("https://api.thin-hornet-0.h.chrysalis-devnet.iota.cafe/");
    const amountToSend = 1000000;
    const newAddress = "atoi1qzt0nhsf38nh6rs4p6zs5knqp6psgha9wsv74uajqgjmwc75ugupx3y7x0r";
    const privateKey = "7955f50024c663167e6f741a88a04c16cffd6b2cdef26635e851330fdeb041912842e5cc739fc27f363ff77cccc4226d0e793ada4dc364c9988fa616a32733d6";
    const publicKey = "2842e5cc739fc27f363ff77cccc4226d0e793ada4dc364c9988fa616a32733d6";

    let bech32Address = Bech32Helper.fromBech32(newAddress, "atoi");
    let newAddressHex = Converter.bytesToHex(bech32Address.addressBytes);

    const nodeInfo = await client.info();

    let walletKeyPair = {publicKey:new Uint8Array(publicKey.match(/.{1,2}/g).map(byte => parseInt(byte, 16))), privateKey: new Uint8Array(privateKey.match(/.{1,2}/g).map(byte => parseInt(byte, 16)))};
    const ed25519Address = new Ed25519Address(walletKeyPair.publicKey);
    const walletAddress = ed25519Address.toAddress();
    const walletAddressHex = Converter.bytesToHex(walletAddress);
    console.log("\tAddress Ed25519", walletAddressHex);
    console.log(
        "\tAddress Bech32",
        Bech32Helper.toBech32(ED25519_ADDRESS_TYPE, walletAddress, nodeInfo.bech32HRP)
    );
    const addressOutputs = await client.addressEd25519Outputs(walletAddressHex);

    const inputsWithKeyPairs: {
        input: IUTXOInput;
        addressKeyPair: IKeyPair;
    }[] = [];

    let availableBalance = 0;

    for (let i = 0; i < addressOutputs.outputIds.length; i++) {
        const output = await client.output(addressOutputs.outputIds[i]);
        if (!output.isSpent) {
            inputsWithKeyPairs.push({
                input: {
                    type: UTXO_INPUT_TYPE,
                    transactionId: output.transactionId,
                    transactionOutputIndex: output.outputIndex
                },
                addressKeyPair: walletKeyPair
            });
            if (output.output.type === SIG_LOCKED_SINGLE_OUTPUT_TYPE) {
                availableBalance += (output.output as ISigLockedSingleOutput).amount;
            }
        }
    }


    const outputs: {
        address: string;
        addressType: number;
        amount: number;
    }[] = [
        // This is the transfer to the new address
        {
            address: newAddressHex,
            addressType: ED25519_ADDRESS_TYPE,
            amount: amountToSend
        },
        // Sending remainder back to own address
        {
            address: walletAddressHex,
            addressType: ED25519_ADDRESS_TYPE,
            amount: availableBalance - amountToSend
        }
    ];

    const { messageId } = await sendAdvanced(client, inputsWithKeyPairs, outputs, {
        key: Converter.utf8ToBytes("WALLET"),
        data: Converter.utf8ToBytes("Not trinity")
    });

    console.log("Created Message Id", messageId);
}

run()
    .then(() => console.log("Done"))
    .catch((err) => console.error(err));

@sikhness
Copy link

@Thoralf-M could you describe what that script does and how to use it?

@Thoralf-M
Copy link
Member Author

@sikhness you have to install iota.js with npm install @iota/iota.js, then set these values with your node and the keys you got from the private tangle setup

   const client = new SingleNodeClient("https://api.thin-hornet-0.h.chrysalis-devnet.iota.cafe/");
   const amountToSend = 1000000;
   const newAddress = "atoi1qzt0nhsf38nh6rs4p6zs5knqp6psgha9wsv74uajqgjmwc75ugupx3y7x0r";
   const privateKey = "7955f50024c663167e6f741a88a04c16cffd6b2cdef26635e851330fdeb041912842e5cc739fc27f363ff77cccc4226d0e793ada4dc364c9988fa616a32733d6";
   const publicKey = "2842e5cc739fc27f363ff77cccc4226d0e793ada4dc364c9988fa616a32733d6";

and run it, then it will transfer the amountToSend to the newAddress you could generate with Firefly or a wallet/client library

@sikhness
Copy link

Hi @Thoralf-M, do you have that same script but created using the Java API? I've been trying to move funds using the Java API and using the Public Key that the one-click-tangle generates and it keeps saying I have a 0 balance for that seed.

@Thoralf-M
Copy link
Member Author

No, doesn't work with the Java library

@sikhness
Copy link

@Thoralf-M is there no way to transfer value from the Genesis account via Java (aka the IOTA rust API) at all? Is this a limitation?

@Thoralf-M
Copy link
Member Author

It depends on how the genesis is created, if the private key would be derived from a seed then it would work, but if it's not like now, then you need a library that supports signing with a private key directly

@sikhness
Copy link

@Thoralf-M, In this case I'm using the one-click-tangle directly, and just using the key-pair that it generates in the key-pair.txt file. Does that key generate from the seed itself?

@Thoralf-M
Copy link
Member Author

No, there is no seed, that's why I opened this issue

@peterokwara
Copy link
Contributor

With hornet v1.20 the mnemonic seed is displayed in the keypar.txt

image

One can use the script here https://github.com/iotaledger/iota.js/blob/dev/packages/iota/examples/transaction/src/index.ts adding the mnemonic and do a transaction with it

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants