Version 1.3.4
* Updated dependencies * Improved documentation, JSDoc and typings
This commit is contained in:
parent
51966303ec
commit
a54611534f
6 changed files with 1092 additions and 3764 deletions
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 Miro Metsänheimo
|
||||
Copyright (c) 2021 Miro Metsänheimo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
|||
231
README.md
231
README.md
|
|
@ -4,37 +4,52 @@
|
|||
[](https://badge.fury.io/js/nanocurrency-web)
|
||||
[](https://github.com/numsu/nanocurrency-web-js/blob/master/LICENSE)
|
||||
|
||||
Toolkit for Nano cryptocurrency client side offline implementations allowing you to build web- and mobile applications using Nano without compromising the user's keys by sending them out of their own device.
|
||||
Toolkit for Nano cryptocurrency client side offline implementations allowing you to build web- and mobile applications using Nano without ever compromising the user's keys by sending them out of their own device.
|
||||
|
||||
The toolkit supports creating and importing wallets and signing blocks on-device. Meaning that the user's keys should never be required to leave the device. And much more!
|
||||
|
||||
## Features
|
||||
|
||||
* Supports BIP32/44 hierarchial deterministic (HD wallet) private key derivation with Nano's derivation path
|
||||
* Generate new HD wallets with a BIP39 mnemonic phrase (Also used in Ledger hardware wallet)
|
||||
* Generate new legacy Nano wallets with mnemonic phrases (Also used in Natrium wallet)
|
||||
* Import wallets with a mnemonic phrase or a seed
|
||||
* Import wallets with the legacy Nano mnemonic phrase or seed
|
||||
* Sign send-, receive- and change representative blocks with a private key
|
||||
* Runs in all web browsers and mobile frameworks built with Javascript (doesn't require server-side NodeJS functions)
|
||||
* Generate new HD wallets (BIP32/44 hierarchial deterministic) with a BIP39 mnemonic phrase (Used in Ledger hardware wallet)
|
||||
* Generate new "legacy" Nano wallets with mnemonic phrases (Used in the Natrium wallet)
|
||||
* Import HD wallets with a mnemonic phrase or a seed
|
||||
* Import "legacy" wallets with the Nano mnemonic phrase or seed
|
||||
* Sign send-, receive- and change (representative) blocks with a private key
|
||||
* Convert Nano units
|
||||
* Sign any strings with the private key, for example you can use the private key as the password by using a private key signature of any string as the password
|
||||
* Verify the signature of a block
|
||||
* Sign any strings with the private key
|
||||
* Verify the signature of any string with the public key
|
||||
* Validate addresses and mnemonic words
|
||||
* Runs in all web browsers and mobile frameworks built with Javascript (doesn't require server-side NodeJS functions)
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
## Installation
|
||||
### From NPM
|
||||
|
||||
```console
|
||||
npm install nanocurrency-web
|
||||
```
|
||||
### In web
|
||||
|
||||
```html
|
||||
<script src="https://unpkg.com/nanocurrency-web@1.3.3" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
NanocurrencyWeb.wallet.generate(...);
|
||||
</script>
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
| WARNING: do not use any of the keys or addresses listed below to send real assets! |
|
||||
| --- |
|
||||
|
||||
#### Wallet handling
|
||||
### Wallets and accounts
|
||||
The wallet is a hexadecimal string called a seed. From this seed you can deterministically derive millions of unique accounts. The first account in a wallet starts at index 0.
|
||||
|
||||
The library is able to generate, import and derive accounts for HD wallets and "legacy" Nano wallets. A HD wallet seed length is 128 hexadecimal characters while a "legacy" Nano wallet seed is 64 characters long.
|
||||
|
||||
These are the two most common used wallets in different applications. A best bet would be to support both of them. For example, when an user wants to import a wallet, you could always generate both wallets and check if either wallet's account at index 0 has a frontier using [the accounts_frontiers RPC](https://docs.nano.org/commands/rpc-protocol/#accounts_frontiers) command.
|
||||
|
||||
```javascript
|
||||
import { wallet } from 'nanocurrency-web'
|
||||
|
|
@ -46,7 +61,7 @@ const wallet = wallet.generate(entropy?, password?)
|
|||
|
||||
// Generates a legacy wallet with a mnemonic phrase, seed and an account
|
||||
// You can provide your own seed to be used instead
|
||||
const wallet = wallet.generateLegacey(seed?)
|
||||
const wallet = wallet.generateLegacy(seed?)
|
||||
|
||||
// Import a wallet with the mnemonic phrase
|
||||
const wallet = wallet.fromMnemonic(mnemonic, seedPassword?)
|
||||
|
|
@ -54,21 +69,21 @@ const wallet = wallet.fromMnemonic(mnemonic, seedPassword?)
|
|||
// Import a wallet with the legacy mnemonic phrase
|
||||
const wallet = wallet.fromLegacyMnemonic(mnemonic)
|
||||
|
||||
// Import a wallet with a seed
|
||||
// Import a wallet with a seed, the mnemonic phrase will be undefined since it's not possible to infer it from the seed
|
||||
const wallet = wallet.fromSeed(seed)
|
||||
|
||||
// Import a wallet with a legacy hex seed
|
||||
// Import a wallet with a legacy seed
|
||||
const wallet = wallet.fromLegacySeed(seed)
|
||||
|
||||
// Derive private keys for a seed, from and to are number indexes
|
||||
// Derive private keys for a seed, from and to are number indexes. The first account index is 0.
|
||||
const accounts = wallet.accounts(seed, from, to)
|
||||
|
||||
// Derive private keys for a legacy seed, from and to are number indexes
|
||||
// Derive private keys for a legacy seed, from and to are number indexes. The first account index is 0.
|
||||
const accounts = wallet.legacyAccounts(seed, from, to)
|
||||
```
|
||||
|
||||
```javascript
|
||||
// The returned wallet JSON format is as follows. The mnemonic phrase will be undefined when importing with a seed.
|
||||
// The returned wallet JSON format is as follows. The mnemonic phrase will be undefined when importing with a seed, unless it's imported with a legacy seed
|
||||
{
|
||||
mnemonic: 'edge defense waste choose enrich upon flee junk siren film clown finish luggage leader kid quick brick print evidence swap drill paddle truly occur',
|
||||
seed: '0dc285fde768f7ff29b66ce7252d56ed92fe003b605907f7a4f683c3dc8586d34a914d3c71fc099bb38ee4a59e5b081a3497b7a323e90cc68f67b5837690310c',
|
||||
|
|
@ -83,23 +98,67 @@ const accounts = wallet.legacyAccounts(seed, from, to)
|
|||
}
|
||||
```
|
||||
|
||||
#### Signing a receive block
|
||||
### Blocks
|
||||
There are three different types of blocks; send, receive and change. While all of these are called "state" blocks, they are interpreted differently based on the data they contain.
|
||||
|
||||
A send block means that the amount of Nano decreases in the account while a receive block means that the amount increases. If the amount stays the same, it's interpreted as a change (representative) block. You are able to change the representative also at the same time when sending or receiving. All blocks are signed with the account's private key.
|
||||
|
||||
The functions are designed to have user friendly usage, but they will return the block exactly the way as the network accepts them. All that is left is to publish the block to the network with the [process RPC command](https://docs.nano.org/commands/rpc-protocol/#process).
|
||||
|
||||
Always fetch the most up to date information for the account from the network using the [account_info RPC command](https://docs.nano.org/commands/rpc-protocol/#account_info).
|
||||
|
||||
If the account hasn't been opened yet (this is the first block), you will need to use the "genesis" as frontier: `0000000000000000000000000000000000000000000000000000000000000000`.
|
||||
|
||||
#### Signing a send block
|
||||
|
||||
```javascript
|
||||
import { block } from 'nanocurrency-web'
|
||||
|
||||
const privateKey = '781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3';
|
||||
const data = {
|
||||
// Your current balance in RAW
|
||||
// Current balance from account info
|
||||
walletBalanceRaw: '5618869000000000000000000000000',
|
||||
|
||||
// Your wallet address
|
||||
fromAddress: 'nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx',
|
||||
|
||||
// The address to send to
|
||||
toAddress: 'nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p',
|
||||
|
||||
// From account info
|
||||
representativeAddress: 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou',
|
||||
|
||||
// Previous block, from account info
|
||||
frontier: '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D',
|
||||
|
||||
// The amount to send in RAW
|
||||
amountRaw: '2000000000000000000000000000000',
|
||||
|
||||
// Generate work on server-side or with a DPOW service
|
||||
// This is optional, you don't have to generate work before signing the transaction
|
||||
work: 'fbffed7c73b61367',
|
||||
}
|
||||
|
||||
// Returns a correctly formatted and signed block ready to be sent to the blockchain
|
||||
const signedBlock = block.send(data, privateKey)
|
||||
```
|
||||
|
||||
#### Signing a receive block
|
||||
```javascript
|
||||
import { block } from 'nanocurrency-web'
|
||||
|
||||
const privateKey = '781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3';
|
||||
const data = {
|
||||
// Your current balance in RAW from account info
|
||||
walletBalanceRaw: '18618869000000000000000000000000',
|
||||
|
||||
// Your address
|
||||
toAddress: 'nano_3kyb49tqpt39ekc49kbej51ecsjqnimnzw1swxz4boix4ctm93w517umuiw8',
|
||||
|
||||
// From wallet info
|
||||
// From account info
|
||||
representativeAddress: 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou',
|
||||
|
||||
// From wallet info
|
||||
// From account info
|
||||
frontier: '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D',
|
||||
|
||||
// From the pending transaction
|
||||
|
|
@ -109,6 +168,7 @@ const data = {
|
|||
amountRaw: '7000000000000000000000000000000',
|
||||
|
||||
// Generate the work server-side or with a DPOW service
|
||||
// This is optional, you don't have to generate work before signing the transaction
|
||||
work: 'c5cf86de24b24419',
|
||||
}
|
||||
|
||||
|
|
@ -116,41 +176,7 @@ const data = {
|
|||
const signedBlock = block.receive(data, privateKey)
|
||||
```
|
||||
|
||||
#### Signing a send block
|
||||
|
||||
```javascript
|
||||
import { block } from 'nanocurrency-web'
|
||||
|
||||
const privateKey = '781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3';
|
||||
const data = {
|
||||
// Current balance from wallet info
|
||||
walletBalanceRaw: '5618869000000000000000000000000',
|
||||
|
||||
// Your wallet address
|
||||
fromAddress: 'nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx',
|
||||
|
||||
// The address to send to
|
||||
toAddress: 'nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p',
|
||||
|
||||
// From wallet info
|
||||
representativeAddress: 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou',
|
||||
|
||||
// Previous block, from wallet info
|
||||
frontier: '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D',
|
||||
|
||||
// The amount to send in RAW
|
||||
amountRaw: '2000000000000000000000000000000',
|
||||
|
||||
// Generate work on server-side or with a DPOW service
|
||||
work: 'fbffed7c73b61367',
|
||||
}
|
||||
|
||||
// Returns a correctly formatted and signed block ready to be sent to the blockchain
|
||||
const signedBlock = block.send(data, privateKey)
|
||||
```
|
||||
|
||||
#### Signing a change representative block
|
||||
|
||||
#### Signing a change (representative) block
|
||||
```javascript
|
||||
import { block } from 'nanocurrency-web'
|
||||
|
||||
|
|
@ -169,21 +195,51 @@ const data = {
|
|||
frontier: '128106287002E595F479ACD615C818117FCB3860EC112670557A2467386249D4',
|
||||
|
||||
// Generate work on the server side or with a DPOW service
|
||||
// This is optional, you don't have to generate work before signing the transaction
|
||||
work: '0000000000000000',
|
||||
}
|
||||
|
||||
// Returns a correctly formatted and signed block ready to be sent to the blockchain
|
||||
const signedBlock = block.representative(data, privateKey)
|
||||
```
|
||||
#### Verifying signatures
|
||||
Cryptocurrencies rely on public key cryptographgy. This means that you can use the public key to validate the signature of the block that is signed with the private key.
|
||||
### Tools
|
||||
|
||||
#### Converting Nano units
|
||||
|
||||
Supported unit values are RAW, NANO, MRAI, KRAI, RAW.
|
||||
|
||||
```javascript
|
||||
import { tools } from 'nanocurrency-web'
|
||||
|
||||
// Convert 1 Nano to RAW
|
||||
const converted = tools.convert('1', 'NANO', 'RAW')
|
||||
|
||||
// Convert 1 RAW to Nano
|
||||
const converted = tools.convert('1000000000000000000000000000000', 'RAW', 'NANO')
|
||||
```
|
||||
|
||||
#### Verifying signatures and signing anything with the private key
|
||||
Cryptocurrencies rely on asymmetric cryptographgy. This means that you can use the public key to validate the signature of the block that is signed with the private key.
|
||||
|
||||
For example implementing client side login with the password being the user's e-mail signed with their private key:
|
||||
|
||||
```javascript
|
||||
import { tools } from 'nanocurrency-web'
|
||||
|
||||
const privateKey = '781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3'
|
||||
const signed = tools.sign(privateKey, 'foo@bar.com')
|
||||
|
||||
// On the backend, verify that the signed value matches the hashed signature in your database
|
||||
```
|
||||
|
||||
You can also validate Nano blocks:
|
||||
```javascript
|
||||
import { tools } from 'nanocurrency-web'
|
||||
|
||||
const valid = tools.verifyBlock(publicKey, block)
|
||||
```
|
||||
##### Using signature verification to prove ownership of the address
|
||||
You are able to challenge an user to prove ownership of a Nano address simply by making the user sign any string with the private key and validating the signature.
|
||||
|
||||
You are able to challenge an user to prove ownership of a Nano address simply by making the user sign any string with the private key and then validating the signature with the public key. You are even able to derive the public key from the Nano address.
|
||||
```javascript
|
||||
import { tools } from 'nanocurrency-web'
|
||||
|
||||
|
|
@ -199,35 +255,10 @@ const publicKey = tools.addressToPublicKey(nanoAddress)
|
|||
|
||||
// Verify the signature using the public key, the signature and the original data
|
||||
const validSignature = tools.verify(publicKey, signature, data)
|
||||
|
||||
```
|
||||
|
||||
#### Converting units
|
||||
|
||||
Supported unit values are RAW, NANO, MRAI, KRAI, RAW.
|
||||
|
||||
```javascript
|
||||
import { tools } from 'nanocurrency-web'
|
||||
|
||||
// Convert 1 Nano to RAW
|
||||
const converted = tools.convert('1', 'NANO', 'RAW')
|
||||
|
||||
// Convert 1 RAW to Nano
|
||||
const converted = tools.convert('1000000000000000000000000000000', 'RAW', 'NANO')
|
||||
```
|
||||
|
||||
#### Signing any data with the private key
|
||||
|
||||
For example implementing client side login with the password being the user's e-mail signed with their private key. Make sure that you double check the signature on the back-end side with the public key.
|
||||
|
||||
```javascript
|
||||
import { tools } from 'nanocurrency-web'
|
||||
|
||||
const privateKey = '781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3'
|
||||
const signed = tools.sign(privateKey, 'foo@bar.com')
|
||||
```
|
||||
|
||||
#### Validating values
|
||||
You are able to validate Nano addresses and mnemonic words.
|
||||
|
||||
```javascript
|
||||
import { tools } from 'nanocurrency-web'
|
||||
|
|
@ -235,32 +266,24 @@ import { tools } from 'nanocurrency-web'
|
|||
// Validate Nano address
|
||||
const valid = tools.validateAddress('nano_1pu7p5n3ghq1i1p4rhmek41f5add1uh34xpb94nkbxe8g4a6x1p69emk8y1d')
|
||||
|
||||
// Validate mnemonic words
|
||||
// Validate mnemonic phrases
|
||||
const valid = tools.validateMnemonic('edge defense waste choose enrich upon flee junk siren film clown finish luggage leader kid quick brick print evidence swap drill paddle truly occur')
|
||||
```
|
||||
|
||||
|
||||
### In web
|
||||
|
||||
```html
|
||||
<script src="https://unpkg.com/nanocurrency-web@1.3.3" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
NanocurrencyWeb.wallet.generate(...);
|
||||
</script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Contributions
|
||||
|
||||
You are welcome to contribute to the module. To develop, use the following commands.
|
||||
|
||||
* `npm install` to install all the dependencies
|
||||
* `npm run build` to build the Typescript code
|
||||
* `npm run test` to run the tests
|
||||
* `npm install` to install dependencies
|
||||
* `npm run build` to build and pack the code
|
||||
* `npm run test` to run tests
|
||||
|
||||
Fork the project, make your changes and request them to be merged with a pull request. Issues are also welcome. If you have any questions, you can find me lurking around the Nano discord server.
|
||||
|
||||
## Donations
|
||||
|
||||
If this helped you in your endeavours and you feel like supporting the developer, feel free to donate some Nano:
|
||||
If this helped you in your endeavours and you feel like supporting the developer, please donate some Nano:
|
||||
|
||||
`nano_1iic4ggaxy3eyg89xmswhj1r5j9uj66beka8qjcte11bs6uc3wdwr7i9hepm`
|
||||
|
||||
If you prefer the old fashioned way, I also have a [GitHub Sponsors account](https://github.com/sponsors/numsu).
|
||||
|
|
|
|||
59
index.ts
59
index.ts
|
|
@ -1,5 +1,3 @@
|
|||
import { TextDecoder } from 'util'
|
||||
|
||||
import BigNumber from 'bignumber.js'
|
||||
|
||||
import AddressGenerator from './lib/address-generator'
|
||||
|
|
@ -32,11 +30,12 @@ const wallet = {
|
|||
* as a parameter and it will be used instead.
|
||||
*
|
||||
* An optional seed password can be used to encrypt the mnemonic phrase so the seed
|
||||
* cannot be derived correctly without the password. Recovering the password is not possible.
|
||||
* cannot be derived correctly without the password. Recovering the wallet without the
|
||||
* password is not possible.
|
||||
*
|
||||
* @param {string} [entropy] - (Optional) 64 byte hexadecimal string entropy to be used instead of the default
|
||||
* @param {string} [entropy] - (Optional) 64 byte hexadecimal string entropy to be used instead of generating it
|
||||
* @param {string} [seedPassword] - (Optional) seed password
|
||||
* @returns the generated mnemonic, seed and account
|
||||
* @returns {Wallet} The wallet
|
||||
*/
|
||||
generate: (entropy?: string, seedPassword?: string): Wallet => {
|
||||
return generator.generateWallet(entropy, seedPassword)
|
||||
|
|
@ -54,8 +53,8 @@ const wallet = {
|
|||
* Generation uses CryptoJS to generate random seed by default. You can give your own seed
|
||||
* as a parameter and it will be used instead.
|
||||
*
|
||||
* @param {string} [seed] - (Optional) 64 byte hexadecimal string seed to be used instead of generating
|
||||
* @returns the generated mnemonic, seed and account
|
||||
* @param {string} [seed] - (Optional) 64 byte hexadecimal string seed to be used instead of generating it
|
||||
* @returns {Wallet} The wallet
|
||||
*/
|
||||
generateLegacy: (seed?: string): Wallet => {
|
||||
return generator.generateLegacyWallet(seed)
|
||||
|
|
@ -74,7 +73,7 @@ const wallet = {
|
|||
* @param {string} mnemonic - The mnemonic phrase. Words are separated with a space
|
||||
* @param {string} [seedPassword] - (Optional) seed password
|
||||
* @throws Throws an error if the mnemonic phrase doesn't pass validations
|
||||
* @returns the wallet derived from the mnemonic (mnemonic, seed, account)
|
||||
* @returns {Wallet} The wallet
|
||||
*/
|
||||
fromMnemonic: (mnemonic: string, seedPassword?: string): Wallet => {
|
||||
return importer.fromMnemonic(mnemonic, seedPassword)
|
||||
|
|
@ -91,7 +90,7 @@ const wallet = {
|
|||
*
|
||||
* @param {string} mnemonic - The mnemonic phrase. Words are separated with a space
|
||||
* @throws Throws an error if the mnemonic phrase doesn't pass validations
|
||||
* @returns the wallet derived from the mnemonic (mnemonic, seed, account)
|
||||
* @returns {Wallet} The wallet
|
||||
*/
|
||||
fromLegacyMnemonic: (mnemonic: string): Wallet => {
|
||||
return importer.fromLegacyMnemonic(mnemonic)
|
||||
|
|
@ -108,7 +107,7 @@ const wallet = {
|
|||
* The address is prefixed with 'nano_'.
|
||||
*
|
||||
* @param {string} seed - The seed
|
||||
* @returns {Wallet} the wallet derived from the seed (seed, account)
|
||||
* @returns {Wallet} The wallet, without the mnemonic phrase because it's not possible to infer backwards
|
||||
*/
|
||||
fromSeed: (seed: string): Wallet => {
|
||||
return importer.fromSeed(seed)
|
||||
|
|
@ -125,8 +124,7 @@ const wallet = {
|
|||
* The address is prefixed with 'nano_'.
|
||||
*
|
||||
* @param {string} seed - The seed
|
||||
* @returns the wallet derived from the seed (seed, account)
|
||||
*
|
||||
* @returns {Wallet} The wallet
|
||||
*/
|
||||
fromLegacySeed: (seed: string): Wallet => {
|
||||
return importer.fromLegacySeed(seed)
|
||||
|
|
@ -142,6 +140,7 @@ const wallet = {
|
|||
* @param {string} seed - The seed
|
||||
* @param {number} from - The start index
|
||||
* @param {number} to - The end index
|
||||
* @returns {Account[]} a list of accounts
|
||||
*/
|
||||
accounts: (seed: string, from: number, to: number): Account[] => {
|
||||
return importer.fromSeed(seed, from, to).accounts
|
||||
|
|
@ -156,6 +155,7 @@ const wallet = {
|
|||
* @param {string} seed - The seed
|
||||
* @param {number} from - The start index
|
||||
* @param {number} to - The end index
|
||||
* @returns {Account[]} a list of accounts
|
||||
*/
|
||||
legacyAccounts: (seed: string, from: number, to: number): Account[] => {
|
||||
return importer.fromLegacySeed(seed, from, to).accounts
|
||||
|
|
@ -173,15 +173,16 @@ const block = {
|
|||
* the recipient address to the 'toAddress' property.
|
||||
* All the NANO amounts should be input in RAW format. The addresses should be
|
||||
* valid Nano addresses. Fetch the current balance, frontier (previous block) and
|
||||
* representative address from the blockchain and generate work for the signature.
|
||||
* representative address from the network.
|
||||
*
|
||||
* The return value of this function is ready to be published to the blockchain.
|
||||
* The return value of this function is ready to be published to the network.
|
||||
*
|
||||
* NOTICE: Always fetch up-to-date account info from the blockchain
|
||||
* before signing the block
|
||||
* NOTICE: Always fetch up-to-date account info from the network
|
||||
* before signing the block.
|
||||
*
|
||||
* @param {SendBlock} data The data for the block
|
||||
* @param {string} privateKey Private key to sign the block
|
||||
* @returns {SignedBlock} the signed block
|
||||
*/
|
||||
send: (data: SendBlock, privateKey: string): SignedBlock => {
|
||||
return blockSigner.send(data, privateKey)
|
||||
|
|
@ -194,16 +195,17 @@ const block = {
|
|||
* For a receive block, put your own address to the 'toAddress' property.
|
||||
* All the NANO amounts should be input in RAW format. The addresses should be
|
||||
* valid Nano addresses. Fetch the current balance, frontier (previous block) and
|
||||
* representative address from the blockchain and generate work for the signature.
|
||||
* representative address from the network.
|
||||
* Input the receive amount and transaction hash from the pending block.
|
||||
*
|
||||
* The return value of this function is ready to be published to the blockchain.
|
||||
* The return value of this function is ready to be published to the network.
|
||||
*
|
||||
* NOTICE: Always fetch up-to-date account info from the blockchain
|
||||
* before signing the block
|
||||
* NOTICE: Always fetch up-to-date account info from the network
|
||||
* before signing the block.
|
||||
*
|
||||
* @param {ReceiveBlock} data The data for the block
|
||||
* @param {string} privateKey Private key to sign the block
|
||||
* @returns {SignedBlock} the signed block
|
||||
*/
|
||||
receive: (data: ReceiveBlock, privateKey: string): SignedBlock => {
|
||||
return blockSigner.receive(data, privateKey)
|
||||
|
|
@ -216,15 +218,15 @@ const block = {
|
|||
* For a change block, put your own address to the 'address' property.
|
||||
* All the NANO amounts should be input in RAW format. The addresses should be
|
||||
* valid Nano addresses. Fetch the current balance, previous block from the
|
||||
* blockchain and generate work for the signature. Set the new representative address
|
||||
* network. Set the new representative address
|
||||
* as the representative.
|
||||
*
|
||||
* NOTICE: Always fetch up-to-date account info from the blockchain
|
||||
* before signing the block
|
||||
* NOTICE: Always fetch up-to-date account info from the network
|
||||
* before signing the block.
|
||||
*
|
||||
* @param {RepresentativeBlock} data The data for the block
|
||||
* @param {string} privateKey Private key to sign the block
|
||||
*
|
||||
* @returns {SignedBlock} the signed block
|
||||
*/
|
||||
representative: (data: RepresentativeBlock, privateKey: string): SignedBlock => {
|
||||
const block: SendBlock = {
|
||||
|
|
@ -249,6 +251,7 @@ const tools = {
|
|||
* @param {string | BigNumber} input The input value
|
||||
* @param {string} inputUnit The unit of the input value
|
||||
* @param {string} outputUnit The unit you wish to convert to
|
||||
* @returns {string} The converted value
|
||||
*/
|
||||
convert: (input: string | BigNumber, inputUnit: string, outputUnit: string): string => {
|
||||
return NanoConverter.convert(input, inputUnit, outputUnit)
|
||||
|
|
@ -259,6 +262,7 @@ const tools = {
|
|||
*
|
||||
* @param {string} privateKey The private key to sign with
|
||||
* @param {...string} input Data to sign
|
||||
* @returns {string} The signature
|
||||
*/
|
||||
sign: (privateKey: string, ...input: string[]): string => {
|
||||
const data = input.map(Convert.stringToHex)
|
||||
|
|
@ -271,6 +275,7 @@ const tools = {
|
|||
* @param {string} publicKey The public key to verify with
|
||||
* @param {string} signature The signature to verify
|
||||
* @param {...string} input Data to verify
|
||||
* @returns {boolean} valid or not
|
||||
*/
|
||||
verify: (publicKey: string, signature: string, ...input: string[]): boolean => {
|
||||
const data = input.map(Convert.stringToHex)
|
||||
|
|
@ -282,8 +287,9 @@ const tools = {
|
|||
*
|
||||
* @param {string} publicKey The public key to verify with
|
||||
* @param {BlockData} block The block to verify
|
||||
* @returns {boolean} valid or not
|
||||
*/
|
||||
verifyBlock: (publicKey: string, block: BlockData) => {
|
||||
verifyBlock: (publicKey: string, block: BlockData): boolean => {
|
||||
const preamble = 0x6.toString().padStart(64, '0')
|
||||
return signer.verify(publicKey, block.signature,
|
||||
preamble,
|
||||
|
|
@ -298,6 +304,7 @@ const tools = {
|
|||
* Validate a Nano address
|
||||
*
|
||||
* @param {string} input The address to validate
|
||||
* @returns {boolean} valid or not
|
||||
*/
|
||||
validateAddress: (input: string): boolean => {
|
||||
return nanoAddress.validateNanoAddress(input)
|
||||
|
|
@ -307,6 +314,7 @@ const tools = {
|
|||
* Validate mnemonic words
|
||||
*
|
||||
* @param {string} input The address to validate
|
||||
* @returns {boolean} valid or not
|
||||
*/
|
||||
validateMnemonic: (input: string): boolean => {
|
||||
return importer.validateMnemonic(input)
|
||||
|
|
@ -316,6 +324,7 @@ const tools = {
|
|||
* Convert a Nano address to a public key
|
||||
*
|
||||
* @param {string} input Nano address to convert
|
||||
* @returns {string} the public key
|
||||
*/
|
||||
addressToPublicKey: (input: string): string => {
|
||||
const cleaned = input
|
||||
|
|
|
|||
4542
package-lock.json
generated
4542
package-lock.json
generated
File diff suppressed because it is too large
Load diff
17
package.json
17
package.json
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "nanocurrency-web",
|
||||
"version": "1.3.3",
|
||||
"version": "1.3.4",
|
||||
"description": "Toolkit for Nano cryptocurrency client side offline integrations",
|
||||
"author": "Miro Metsänheimo <miro@metsanheimo.fi>",
|
||||
"license": "MIT",
|
||||
|
|
@ -30,17 +30,16 @@
|
|||
"test": "mocha --reporter spec"
|
||||
},
|
||||
"dependencies": {
|
||||
"bignumber.js": "9.0.0",
|
||||
"bignumber.js": "9.0.1",
|
||||
"blakejs": "1.1.0",
|
||||
"crypto-js": "3.1.9-1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "12.7.12",
|
||||
"chai": "4.2.0",
|
||||
"mocha": "6.2.1",
|
||||
"ts-loader": "6.2.0",
|
||||
"typescript": "3.6.3",
|
||||
"webpack": "4.41.1",
|
||||
"webpack-cli": "3.3.9"
|
||||
"chai": "4.3.4",
|
||||
"mocha": "9.0.0",
|
||||
"ts-loader": "9.2.3",
|
||||
"typescript": "4.3.2",
|
||||
"webpack": "5.38.1",
|
||||
"webpack-cli": "4.7.2"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,6 +151,11 @@ describe('derive more accounts from the same seed test', () => {
|
|||
expect(result[14].privateKey).to.equal('5f12e37c64daf2501c6a6a20614fd8d977fed65b5b5f0b045ec997f2ed2f53ca')
|
||||
expect(result[14].publicKey).to.equal('f93a61018e07825a095e8cf7bdce9242e9c12c5c41a55de597a2be93fa41306b')
|
||||
expect(result[14].address).to.equal('nano_3ybte61rw3w4da6ox59qqq9b6iqbr6p7rif7dqkshaoykhx64e5dbp4o1ua1')
|
||||
|
||||
const result2 = wallet.accounts(
|
||||
'0dc285fde768f7ff29b66ce7252d56ed92fe003b605907f7a4f683c3dc8586d34a914d3c71fc099bb38ee4a59e5b081a3497b7a323e90cc68f67b5837690310c',
|
||||
1000000, 1000099)
|
||||
expect(result2.length).to.equal(100)
|
||||
})
|
||||
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue