2

i wanna to craete wallet for user in nodejs and substrate . i using these codes for connect to substrate node and create a wallet :

const { ApiPromise, WsProvider } = require('@polkadot/api');
const { Keyring } = require('@polkadot/keyring');
const { cryptoWaitReady, mnemonicGenerate, mnemonicToMiniSecret, schnorrkelKeypairFromSeed } = require('@polkadot/util-crypto');
const { TypeRegistry } = require('@polkadot/types'); // Add this import

class PolkadotWrapper {
  constructor(endpoint) {
    this.endpoint = endpoint;
    this.api = null;
  }

  async connect() {
    const wsProvider = new WsProvider(this.endpoint);
    const registry = new TypeRegistry();
  
    this.api = await ApiPromise.create({
      provider: wsProvider,
      registry, 
      types: {}, 
    });
  
    await this.api.isReady;
  }
  

  createAccount() {
    const mnemonic = mnemonicGenerate();
    const keyring = new Keyring({ type: 'sr25519' });
    const newAccount = keyring.createFromUri(mnemonic);
  
    return {
      instance: newAccount, 
      mnemonic,
      address: newAccount.address,
      publicKey: newAccount.publicKey.toString('hex'),
    };
  }
  

and it create a wallet for user but when i need to call this function whith that created account with `createAccount` function : 

  const newAccount = wrapper.createAccount();
  console.log('New account:', newAccount.instance);

transafer function :

  async transfer(fromAccount, toAddress, amount) {
    if (!this.api) throw new Error('API not connected');

    // Prepare the extrinsic
    const extrinsic = this.api.tx.balances.transfer(toAddress, amount);

    // Sign and send the extrinsic
    const { nonce } = await this.api.query.system.account(fromAccount.address);
    const signedExtrinsic = extrinsic.sign(fromAccount, { nonce });

    // Submit the transaction and return the result
    const result = await new Promise((resolve, reject) => {
      signedExtrinsic.send(({ status, events }) => {
        if (status.isInBlock || status.isFinalized) {
          events.forEach(({ event }) => {
            if (event.section === 'system' && event.method === 'ExtrinsicFailed') {
              reject(new Error('Extrinsic failed'));
            } else if (event.section === 'system' && event.method === 'ExtrinsicSuccess') {
              resolve({ blockHash: status.asInBlock.toHex() });
            }
          });
        }
      }).catch((error) => {
        reject(error);
      });
    });

    return result;
  }

it show me this error :

Transaction failed: Cannot read properties of undefined (reading 'specVersion')

what the problem ?

1 Answer 1

2

Try initializing your API like so:

const wsProvider = new WsProvider(this.endpoint);
const api = await ApiPromise.create({ provider: wsProvider });

Also, here is some working code that may help you.

import { ApiPromise, WsProvider } from "@polkadot/api"
import { mnemonicGenerate } from '@polkadot/util-crypto'
import { Keyring } from '@polkadot/keyring';

// const wsProvider = new WsProvider('wss://rpc.polkadot.io');
const wsProvider = new WsProvider("ws://127.0.0.1:54185");
const api = await ApiPromise.create({ provider: wsProvider });

const mnemonic = mnemonicGenerate();
const keyring = new Keyring({ type: 'sr25519' });
const brunoPair = keyring.addFromUri(mnemonic, { name: 'Bruno' }, 'sr25519');
console.log(brunoPair.meta.name, 'has address', brunoPair.address);

// For testing purposes
const alicePair = keyring.addFromUri('//Alice');
const bobPair = keyring.addFromUri('//Bob');

export const createAccount = async () => {

    const mnemonic = mnemonicGenerate();
    const keyring = new Keyring({ type: 'sr25519' });
    const pair = keyring.addFromUri(mnemonic, { name: 'Bruno' }, 'sr25519');
    console.log(pair.meta.name, 'has address', pair.address);

    return {
      pair, 
      mnemonic,
      address: pair.address,
      publicKey: pair.publicKey.toString('hex'),
    };
  }

  console.log(`New account: {}`, await createAccount());

  const transfer = async (fromAccount, toAddress, amount) => {
    
    const { nonce } = await api.query.system.account(fromAccount);

    // You need to get the account from the keyring
    const fromAccountPair = keyring.getPair(fromAccount);

    api.tx.balances.transfer(toAddress, amount).signAndSend(fromAccountPair, { nonce }, ({ events = [], status }) => {
        console.log('Transaction status:', status.type);
  
        if (status.isInBlock) {
          console.log('Included at block hash', status.asInBlock.toHex());
          console.log('Events:');
  
          events.forEach(({ event: { data, method, section }, phase }) => {
            console.log('\t', phase.toString(), `: ${section}.${method}`, data.toString());
          });
        } else if (status.isFinalized) {
          console.log('Finalized block hash', status.asFinalized.toHex());
  
          process.exit(0);
        }
      });
  }

  // transfer from Alice to Bob
  transfer(alicePair.address, bobPair.address, 7000000000000000);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.