ESMでの書き方です。
ニーモニックから生成する
ニーモニックを生成する
デスクトップウォレットと同じようにニーモニックを生成してみます。引数をデフォルト値にするとデスクトップウォレットと互換性のあるニーモニックが生成されます。
import { Bip32 } from 'symbol-sdk';
// ニーモニック生成
const bip32 = new Bip32();
const mnemonic = bip32.random();
console.log(`mnemonic: ${mnemonic}`);
実はBip32
の第二引数で言語指定が出来ます。japanese
を渡してあげると「ひらがな」のニーモニックが生成されます。
import { Bip32 } from 'symbol-sdk';
import { SymbolFacade } from 'symbol-sdk/symbol';
// ニーモニック生成(日本語)
const bip32Jp = new Bip32(SymbolFacade.BIP32_CURVE_NAME, 'japanese');
const mnemonicJp = bip32Jp.random();
console.log(`mnemonic: ${mnemonicJp}`);
もちろんこれは言語が異なるので、英語のみ対応しているデスクトップウォレットでは、使用できません。また、ニーモニックの言語間の変換も不可能のようです。なので、英語以外で出力すると汎用性が低下します。日本語ニーモニックをアプリに組み込む場合は、日本語ニーモニックのデメリットを記載したほうが良いでしょう。
コード例
英語と日本語のニーモニックをそれぞれ出力するコードです。
import { Bip32 } from 'symbol-sdk';
import { SymbolFacade } from 'symbol-sdk/symbol';
// ニーモニック生成
const bip32 = new Bip32();
const mnemonic = bip32.random();
console.log(`mnemonic: ${mnemonic}`);
// ニーモニック生成(日本語)
const bip32Jp = new Bip32(SymbolFacade.BIP32_CURVE_NAME, 'japanese');
const mnemonicJp = bip32Jp.random();
console.log(`mnemonic: ${mnemonicJp}`);
実行結果
ランダムなので毎回結果は異なります。
> tsx src/generateMnemonic.ts
mnemonic: plunge ritual gospel ivory ...
mnemonic: いずみ いこつ おくじょう いじわる ...
ニーモニックからアカウントを生成する
生成した英語ニーモニックからアカウントを生成してみましょう。
秘密鍵を生成出来るBip32Node
をbip32.fromMnemonic(mnemonic, passwd)
を使って生成します。第二引数のパスワードで結果が変わってくるのですが、デスクトップウォレットは固定で空文字となってます。なお、パスワードを変更することでウォレット特有のニーモニックとアカウントの紐付けができますが、ユーザーに入力を求めるかアプリ専用のパスワードを設定することで、セキュリティが向上するかと思います。
import { Bip32 } from 'symbol-sdk';
// ニーモニック
const mnemonic = 'plunge ritual gospel ivory ...';
// ニーモニックパスワード
const passwd = '';
// Bip32Node生成
const bip32 = new Bip32();
const bip32Node = bip32.fromMnemonic(mnemonic, passwd);
Bip32Nodeは子孫を作ることができ、それぞれ異なる秘密鍵を持っています。子孫Bip32Nodeは、定数として設定されたパスを元に生成されます。ニーモニック、パスワード、子孫Bip32Node生成時のパスの番号が同じであれば、毎回同じアカウントが導出されます。
// faced生成
const facade = new SymbolFacade(Network.TESTNET);
// 10件アカウントを生成する
const maxAccountCount = 10;
for (let i = 0; i < maxAccountCount; i++) {
// Bip32Path生成
const bip32Path = facade.bip32Path(i);
// Bip32Pathから子孫Bip32Path生成
const childBip32Node = bip32Node.derivePath(bip32Path);
// 子孫Bip32Pathからキーペア生成
const keyPair = SymbolFacade.bip32NodeToKeyPair(childBip32Node);
// 公開鍵からアドレス生成
const address = new Address(
facade.network.publicKeyToAddress(keyPair.publicKey)
);
// 表示
console.log(`[${i}]`, address.toString(), keyPair.privateKey.toString());
}
コード例
注意:ニーモニックは省略してます。
import { Bip32 } from 'symbol-sdk';
import { Address, Network, SymbolFacade } from 'symbol-sdk/symbol';
// ニーモニック
const mnemonic = 'plunge ritual gospel ivory ...';
// ニーモニックパスワード
const passwd = '';
// Bip32Node生成
const bip32 = new Bip32();
const bip32Node = bip32.fromMnemonic(mnemonic, passwd);
// faced生成
const facade = new SymbolFacade(Network.TESTNET);
// 10件アカウントを生成する
const maxAccountCount = 10;
for (let i = 0; i < maxAccountCount; i++) {
// Bip32Path生成
const bip32Path = facade.bip32Path(i);
// Bip32Pathから子孫Bip32Path生成
const childBip32Node = bip32Node.derivePath(bip32Path);
// 子孫Bip32Pathからキーペア生成
const keyPair = SymbolFacade.bip32NodeToKeyPair(childBip32Node);
// 公開鍵からアドレス生成
const address = new Address(
facade.network.publicKeyToAddress(keyPair.publicKey)
);
// 表示
console.log(`[${i}]`, address.toString(), keyPair.privateKey.toString());
}
実行結果
ニーモニックが同じであれば、同じアカウントが生成されます。ニーモニックパスワードをデスクトップウォレットと同じにしているので、デスクトップウォレットでも同じアカウントが生成されます。
> tsx src/generateAccountFromMnemonic.ts
[0] TAIUJZDTWWTDTQRGHYNN5XTIMGMR6E7OK7C46FQ B150************************************************************
[1] TBUC42PS2BCMLNGZW63G6UE7DT63LGTTPVHUAIY A99F************************************************************
[2] TBEH6FJXD5GWZQJCE42DEELDVBTFDWI3AYCTS6Y C53D************************************************************
[3] TBDNBIIOKVXUA2QL26CXTKRSK6FNZIGO2FLJW2I 7297************************************************************
[4] TCTQHGNJKB4HQ36KAIMTAT2BOSCZBTUANCG4TBQ 79AE************************************************************
[5] TA42X7GHUTD6FKPG2U3L2MKCTX4EYP73AE6REWQ FAD6************************************************************
[6] TDEPURXXMXH2ECXRC77OX3FXM6VCHMBHRTD3ZII A15B************************************************************
[7] TBYIJ7OSYW2N3RIEXDNGC3OXQA2F7KOPUQNET5Y 21A4************************************************************
[8] TADGBFLMBZGILRKCCXPMZR2J6CFRRHVX5MOCLJY 85A1************************************************************
[9] TB7HGQZ5XHJWKH3R55FIT6HTQHTOF25LD2WU2GA E78C************************************************************
秘密鍵から生成する
秘密鍵の生成
秘密鍵は1コードで生成出来ます。
import { PrivateKey } from "symbol-sdk";
// 秘密鍵ランダム取得
const privateKey = PrivateKey.random();
秘密鍵からアカウントを生成する
生成した秘密鍵からキーペアを生成します。
// キーペア生成
const keyPair = new KeyPair(privateKey);
// アドレス
const facade = new SymbolFacade(Network.TESTNET);
const address = new Address(
facade.network.publicKeyToAddress(keyPair.publicKey)
);
コード例
import { PrivateKey } from 'symbol-sdk';
import { KeyPair, SymbolFacade, Network, Address } from 'symbol-sdk/symbol';
// 秘密鍵ランダム取得
const privateKey = PrivateKey.random();
// キーペア生成
const keyPair = new KeyPair(privateKey);
// アドレス
const facade = new SymbolFacade(Network.TESTNET);
const address = new Address(
facade.network.publicKeyToAddress(keyPair.publicKey)
);
// 表示
console.log(`privateKey: ${privateKey.toString()}`);
console.log(`publicKey : ${keyPair.publicKey.toString()}`);
console.log(`address : ${address.toString()}`);
実行結果
秘密鍵をランダムに生成しているので、実行する度にアドレス等が変わります。
> tsx .\src\generateAccountFromPrivateKey.ts
privateKey: 3106************************************************************
publicKey : C91C866CBA5E9DCFF436FED9CB5740DDB5FE89C3C009D5AB92262E664D0313C3
address : TAPHR7GPU3RNQZLQ5VC7NWD2K25M5PHIS5RPOEA