polkadot-js / common

Utilities and base libraries for use across polkadot-js for Polkadot and Substrate. Includes base libraries, crypto helpers and cross-environment helpers.
Apache License 2.0
255 stars 145 forks source link

create a valid wallet for polkadot network #907

Closed samanyousefi closed 3 years ago

samanyousefi commented 3 years ago

how i can create a valid public-private key to using in the Polkadot network.

jacogr commented 3 years ago

See https://polkadot.js.org/docs/keyring

samanyousefi commented 3 years ago

@jacogr I used that like sample code but the result is not a valid address

description about dot coin valid structure https://wiki.polkadot.network/docs/en/learn-accounts

sample code:

// modules

      const {
                mnemonicGenerate,
                mnemonicToMiniSecret,
                mnemonicValidate,
                naclKeypairFromSeed,
                naclKeypairFromRandom
            } = require('@polkadot/util-crypto');

// Codes

        // Create mnemonic string for Alice using BIP39
        const mnemonicAlice = mnemonicGenerate();

        console.log(`Generated mnemonic: ${mnemonicAlice}`);

        // Validate the mnemic string that was generated
        const isValidMnemonic = mnemonicValidate(mnemonicAlice);

        console.log(`isValidMnemonic: ${isValidMnemonic}`);

        // Create valid Substrate-compatible seed from mnemonic
        const seedAlice = mnemonicToMiniSecret(mnemonicAlice);

        // Generate new public/secret keypair for Alice from the supplied seed
        // const { publicKey, secretKey } = naclKeypairFromSeed(seedAlice);
        const { publicKey, secretKey } = naclKeypairFromRandom();

        console.log(publicKey, secretKey)
        console.log(Buffer.from(publicKey).toString('hex'))
        console.log(Buffer.from(secretKey).toString('hex'))

        }

Result:

// Public Key Uint8Array(32) [ 153, 130, 213, 236, 106, 230, 48, 97, 14, 214, 110, 131, 142, 80, 183, 130, 37, 174, 64, 26, 166, 130, 35, 251, 78, 60, 119, 73, 33, 216, 205, 203 ]

// Secret Key Uint8Array(64) [ 133, 224, 82, 216, 52, 55, 143, 131, 154, 87, 207, 36, 47, 236, 139, 165, 124, 44, 131, 34, 238, 239, 111, 226, 232, 22, 55, 122, 13, 179, 0, 189, 153, 130, 213, 236, 106, 230, 48, 97, 14, 214, 110, 131, 142, 80, 183, 130, 37, 174, 64, 26, 166, 130, 35, 251, 78, 60, 119, 73, 33, 216, 205, 203 ]

// Public Key 9982d5ec6ae630610ed66e838e50b78225ae401aa68223fb4e3c774921d8cdcb

// Secret Key 85e052d834378f839a57cf242fec8ba57c2c8322eeef6fe2e816377a0db300bd9982d5ec6ae630610ed66e838e50b78225ae401aa68223fb4e3c774921d8cdcb

jacogr commented 3 years ago

What is not a valid address? This creates valid pairs as per specification - and all test-cases align with Subkey. Additionally is is used by all the Substrate-compatible JS wallets in the ecosystem. (Some sadly use Bitcoin-era non-standard derivations, which means it is not portable to substrate chains)

What are you expecting that you don't see?

Since you don't use the keyring recommendation, if you expect to see an address, use encodeAddress on the publicKey.

samanyousefi commented 3 years ago

in the above code, the publicKey is not a valid publicKey for Polkadot, a valid public key must start with 1 character and also must be valid on the website: polkascan.io I just want a code or solution for creating the polka dot wallet.

jacogr commented 3 years ago

No. What you are viewing on Polkascan, or Subscan, or Polkadot.js.org or Polkawallet, etc. is the publicKey encoded with ss58 to an address.

Public key bytes themselves do not start with a 1 in Polkadot, the ss58 encoded display format does.

So, as suggested - encodeAddress(publicKey, 0) (the 0 is the Polkadot ss58 prefix, 2 for Kusama, etc.)

See https://polkadot.js.org/docs/keyring/start/ss58 for an intro to ss58.

samanyousefi commented 3 years ago

thank you @jacogr, i used this document examples codes, and that returned for me some addresses:

Polkadot 1NthTCKurNHLW52mMa6iA8Gz7UFYW5UnM3yTSpVdGu4Th7h Substrate generic 5CSbZ7wG456oty4WoiX6a1J88VUbrCXLhrKVJ9q95BsYH4TZ Kusama CxDDSH8gS7jecsxaRL9Txf8H5kqesLXAEAEgp76Yz632J9M

my target publicKey is Polkadot, but Polkscan result is: "No results found for 1NthTCKurNHLW52mMa6iA8Gz7UFYW5UnM3yTSpVdGu4Th7h"

you can see that message in this URL: https://polkascan.io/polkadot/analytics/search/1NthTCKurNHLW52mMa6iA8Gz7UFYW5UnM3yTSpVdGu4Th7h

and my other question is how I can get the private key of that created publicKey i above.

jacogr commented 3 years ago

Polkascan will only show addresses that have received funds - before that and without an existential deposit, they do not appear in the chain state. (Same as Subscan). So it is 100% correct that they cannot find the address, since it has not have funds.

The private key is not derivable from the publicKey - that would mean that anybody with an address has access to the funds. They are a pair. The keyring doesn't even expose the secretKey in any getters. In your example above, you create a public/private pair.

samanyousefi commented 3 years ago

so i cant create a wallet for polka dot with this package?

jacogr commented 3 years ago

This is how an account shows up on an explorer -

Accounts are only reflected in the chain state when it has an existential value, without it, it doesn't exist. On the last step above, when the account has > existential, the chain emits a new account event, see for instance https://polkascan.io/polkadot/event?module=System&event=NewAccount&page=1, the explorers listen to these events and will start indexing the account.

When an account has been in the state and does get reaped (balance falls below existential) and the chain emits a killed account event, the explorers will still have the history for this account in their databases and will continue showing it. (Although at that point, the chain state will have no references to the address anymore)

TL:DR Any newly created public/private combo can be used and can receive funds - but until it has received a value > existential deposit and the chain indicated that the account has been created, it will not be reflected in any explorers.

samanyousefi commented 3 years ago

thank you, i get it but please tell me after i run the following code and i get the public key how i can send money, i don't have a private key.

// known mnemonic, well, now it is - doesn't use it for funds const MNEMONIC = 'sample split bamboo west visual approve brain fox arch impact relief smile';

// type: ed25519, ssFormat: 42 (all defaults) const keyring = new Keyring(); const pair = keyring.createFromUri(MNEMONIC);

// use the default as setup on init // 5CSbZ7wG456oty4WoiX6a1J88VUbrCXLhrKVJ9q95BsYH4TZ console.log('Substrate generic', pair.address);

// adjust the default ss58Format for Kusama // CxDDSH8gS7jecsxaRL9Txf8H5kqesLXAEAEgp76Yz632J9M keyring.setSS58Format(2); console.log('Kusama', pair.address);

// adjust the default ss58Format for Polkadot // 1NthTCKurNHLW52mMa6iA8Gz7UFYW5UnM3yTSpVdGu4Th7h keyring.setSS58Format(0); console.log('Polkadot', pair.address);

samanyousefi commented 3 years ago

in the following code, i have an address and also a private key (secret) but the secret key is an array, how i can encode that like publicKey with an encoded address method.

  const {
        mnemonicGenerate,
        mnemonicToMiniSecret,
        mnemonicValidate,
        naclKeypairFromSeed,
        naclKeypairFromRandom,encodeAddress
    } = require('@polkadot/util-crypto');

    const {
        Keyring
    } = require('@polkadot/keyring');

        // Create mnemonic string for Alice using BIP39
        const mnemonicAlice = mnemonicGenerate();

        // Validate the mnemic string that was generated
        const isValidMnemonic = mnemonicValidate(mnemonicAlice);

        // Create valid Substrate-compatible seed from mnemonic
        const seedAlice = mnemonicToMiniSecret(mnemonicAlice);

        const { publicKey, secretKey } = naclKeypairFromRandom();

        console.log(encodeAddress(publicKey, 0),'public')
        console.log(secretKey,'secret')

following code result :

public key: 14cPULDYejY4nwi5AiRDTzPHxhiDMqwja1w2rQrxkjTLeivT

private key: Uint8Array(64) [ 32, 189, 11, 140, 32, 149, 221, 96, 231, 77, 255, 79, 164, 125, 134, 200, 229, 172, 188, 192, 32, 91, 50, 50, 228, 55, 76, 93, 224, 247, 78, 174, 159, 177, 239, 53, 183, 206, 223, 74, 47, 15, 101, 254, 124, 70, 101, 112, 67, 123, 188, 51, 142, 23, 174, 135, 183, 159, 148, 177, 161, 19, 200, 249 ]

jacogr commented 3 years ago

The private key doesn't get encoded as an address. The public key does.

The keyring doesn't need to expose the private key since it allows you to perform signing operations with the pair - signing is the only area where a private key is needed.

samanyousefi commented 3 years ago

how can I store this private key in the database?

jacogr commented 3 years ago

If you wish to store it directly - not using the keyring exports (i.e. the toJSON), your approach above of creating it directly via the lower-level libraries is best.

polkadot-js-bot commented 3 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue if you think you have a related problem or query.