diff --git a/.eslintrc.js b/.eslintrc.js index fcb5589..0b9d0f5 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,7 @@ module.exports = { parser: 'babel-eslint', extends: 'standard', - plugins: ['mocha'], + plugins: ['mocha', 'chai-friendly'], parserOptions: { 'ecmaVersion':2017 }, @@ -9,6 +9,8 @@ module.exports = { rules: { 'space-before-function-paren': ['error', 'never'], 'no-underscore-dangle': 0, - 'mocha/no-exclusive-tests': 'error' + 'mocha/no-exclusive-tests': 'error', + "no-unused-expressions": 0, + "chai-friendly/no-unused-expressions": 2 } } diff --git a/lib/community.js b/lib/community.js new file mode 100644 index 0000000..bbf47d5 --- /dev/null +++ b/lib/community.js @@ -0,0 +1,24 @@ +import Transaction from './transaction' + +/** + * Community managing class + */ +class Community { + constractor(wallet) { + this.wallet = wallet + } + /** + * create new Community. + * @param name (unique) as communityId. + * @return {Promise} + */ + async create(name) { + return new Transaction() + } + + get [Symbol.toStringTag]() { + return 'Community' + } +} + +export default Community diff --git a/lib/masa.js b/lib/masa.js index 8a907c4..1b0b722 100644 --- a/lib/masa.js +++ b/lib/masa.js @@ -1,5 +1,28 @@ -function masa(provider) { - console.log('masa.js') +import MasaPoint from './masa_point' +import MasaCoin from './masa_coin' + +/** + * Masa system client library class. + */ +class Masa { + /** + * @constructor + */ + constructor() { + console.log('masa.js') + const provider = {} + this.point = new class extends MasaPoint { + feedback(to, communityId, feelingsId, msg) { + throw new TypeError('Not support function. Please use MasaTx.') + } + }(provider, null) + this.coin = new class extends MasaCoin { + transfer(address) { + throw new TypeError('Not support function. Please use MasaTx.') + } + }(provider, null) + } } +const masa = new Masa() export default masa diff --git a/lib/masa_coin.js b/lib/masa_coin.js new file mode 100644 index 0000000..e957ec3 --- /dev/null +++ b/lib/masa_coin.js @@ -0,0 +1,33 @@ +import Transaction from './transaction' + +/** + * MasaCoin managing class + */ +class MasaCoin { + constructor(provider, wallet) { + this.provider = provider + this.wallet = wallet + } + /** + * Get the balance of coin. + * @param address to query the balance of. + * @returns {Promise} amount of coin. + */ + async balanceOf(address) { + // TODO: implement + return 100 + } + + /** + * Send coin to other user. + * @param address receiver address + * @param amount sending amount + * @return {Promise} + */ + async transfer(address, amount) { + // TODO: implement + return new Transaction() + } +} + +export default MasaCoin diff --git a/lib/masa_point.js b/lib/masa_point.js new file mode 100644 index 0000000..a854018 --- /dev/null +++ b/lib/masa_point.js @@ -0,0 +1,62 @@ +import Transaction from './transaction' + +/** + * MasaPoint managing class. + * This class provide functions for access to MasaPoint Smart Contract on Ethereum. + */ +class MasaPoint { + /** + * @constructor + * @param provider require for explorer functions + * @param wallet require for signed functions + */ + constructor(provider, wallet) { + this.provider = provider + this.wallet = wallet + } + /** + * Get the amount of valid points. + * @param address the owner of masa point + * @returns {Promise} point of the user + */ + async amountOf(address) { + // TODO: implement + if (address === '0x6861766520636f696e20697300000000000000b8') { + return 200 + } + return 500 + } + + /** + * Get the amount of valid points in a specific community. + * @param address the owner of masa point + * @param communityId community id + * @returns {Promise} point of the user in the community + */ + async communityAmountOf(address, communityId) { + // TODO: implement + return 200 + } + + /** + * Create feedback raw transaction. + * @param to feedback received user address + * @param communityId the community regarding of feedback + * @param feelingsId Gratitude: 1 / Empathy: 2 /Support: 3 + * @param msg reason for feelings + * @returns {Promise} + */ + async feedback(to, communityId, feelingsId, msg) { + // TODO: implement + if (this.wallet === undefined) { + throw new TypeError('Wallet is NULL! need for sign.') + } + return new Transaction() + } + + get [Symbol.toStringTag]() { + return 'MasaPoint' + } +} + +export default MasaPoint diff --git a/lib/masa_tx.js b/lib/masa_tx.js new file mode 100644 index 0000000..e40f15b --- /dev/null +++ b/lib/masa_tx.js @@ -0,0 +1,40 @@ +import Wallet from './wallet' +import MasaPoint from './masa_point' +import MasaCoin from './masa_coin' +import Community from './community' + +/** + * MasaTx class provide functions that create signed transaction. + * This class needs wallet for pick up private key. + * + * Usage: + * const masaTx = new MasaTx() // generate new wallet. + * or + * const masaTx = new MasaTx(mnemonic) // restore wallet from specify mnemonic + * + * masaTx.point.feedback(~~~~) // return signed transaction for Masa Point Feedback. + * masaTx.coin.transfer(~~~) // return signed transaction for Masa Coin Transfer. + * masaTx.community.create(~~~) // return signed transaction for Community creation. + */ +class MasaTx { + constructor(mnemonic = '') { + mnemonic = mnemonic === undefined || mnemonic === '' ? Wallet.generateMnemonic() : mnemonic + this.wallet = new Wallet(mnemonic) + this.point = new class extends MasaPoint { + amountOf(address) { + throw new TypeError('Not support function. Please use Masa.') + } + communityAmountOf(address, communityId) { + throw new TypeError('Not support function. Please use Masa.') + } + }(null, this.wallet) + this.coin = new class extends MasaCoin { + async balanceOf() { + throw new TypeError('Not support function. Please use Masa.') + } + }(null, this.wallet) + this.community = new Community(this.wallet) + } +} + +export default MasaTx diff --git a/lib/transaction.js b/lib/transaction.js new file mode 100644 index 0000000..044d43f --- /dev/null +++ b/lib/transaction.js @@ -0,0 +1,37 @@ +/** + * Class for Provide convenience access to Ethereum Transaction. + */ +class Transaction { + /** + * sign this transaction + * @param privateKey + */ + signature(privateKey) { + // TODO: implement + } + + /** + * serialize to json format + * @return {JSON} json formatted transaction + */ + toJSON() { + // TODO: implement + return { + to: '', + nonce: 2, + gas: 0x01, + gasPrice: 20 * 10 ** 9, + data: '0x0000000001', + chainId: 4447, + v: '', + s: '', + r: '' + } + } + + get [Symbol.toStringTag]() { + return 'Transaction' + } +} + +export default Transaction diff --git a/lib/wallet.js b/lib/wallet.js new file mode 100644 index 0000000..04f4ccc --- /dev/null +++ b/lib/wallet.js @@ -0,0 +1,48 @@ +import bip39 from 'bip39' +import hdkey from 'ethereumjs-wallet/hdkey' + +/** + * Masa Wallet class. + * Provide simple wallet functions. + * Usage: + * const mnemonic = Wallet.generateMnemonic() + * const wallet = new Wallet(mnemonic) + * const privateKey = wallet.privateKey // return Buffer + * const address = wallet.address // return string + */ +class Wallet { + get HD_PATH() { + return "m/44'/60'/0'/0/0" + } + + /** + * generate mnemonic of master seed. + * @return {string} mnemonic + */ + static generateMnemonic() { + return bip39.generateMnemonic() + } + + /** + * create HDWallet from master seed mnemonic. + * @constructor + * @param mnemonic {string} + */ + constructor(mnemonic) { + if (!bip39.validateMnemonic(mnemonic)) { + throw new TypeError('invalid mnemonic!') + } + this.mnemonic = mnemonic + this._hdwallet = hdkey.fromMasterSeed(bip39.mnemonicToSeed(mnemonic)) + this._wallet = this._hdwallet.derivePath(this.HD_PATH).getWallet() + this.address = '0x' + this._wallet.getAddress().toString('hex') + this.privateKey = this._wallet.getPrivateKey() + this.publicKey = this._wallet.getPublicKey() + } + + get [Symbol.toStringTag]() { + return 'Wallet' + } +} + +export default Wallet diff --git a/package-lock.json b/package-lock.json index 8bd7676..3e6aa6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -631,6 +631,17 @@ "regenerator-transform": "^0.13.3" } }, + "@babel/plugin-transform-runtime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.0.0.tgz", + "integrity": "sha512-yECRVxRu25Nsf6IY5v5XrXhcW9ZHomUQiq30VO8H7r3JYPcBJDTcxZmT+6v1O3QKKrDp1Wp40LinGbcd+jlp9A==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "resolve": "^1.8.1" + } + }, "@babel/plugin-transform-shorthand-properties": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0.tgz", @@ -689,6 +700,16 @@ "regexpu-core": "^4.1.3" } }, + "@babel/polyfill": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.0.0.tgz", + "integrity": "sha512-dnrMRkyyr74CRelJwvgnnSUDh2ge2NCTyHVwpOdvRMHtJUyxLtMAfhBN3s64pY41zdw0kgiLPh6S20eb1NcX6Q==", + "dev": true, + "requires": { + "core-js": "^2.5.7", + "regenerator-runtime": "^0.11.1" + } + }, "@babel/preset-env": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.0.0.tgz", @@ -738,6 +759,23 @@ "semver": "^5.3.0" } }, + "@babel/runtime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0.tgz", + "integrity": "sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.12.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", + "dev": true + } + } + }, "@babel/template": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0.tgz", @@ -1085,6 +1123,11 @@ "acorn": "^5.0.3" } }, + "aes-js": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.1.tgz", + "integrity": "sha512-cEA0gBelItZZV7iBiL8ApCiNgc+gBWJJ4uoORhbu6vOqAJ0UL9wIlxr4RI7ij9SSVzy6AnPwiu37kVYiHCl3nw==" + }, "ajv": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", @@ -1364,6 +1407,14 @@ } } }, + "base-x": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.4.tgz", + "integrity": "sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "base64-js": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", @@ -1382,6 +1433,31 @@ "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", "dev": true }, + "bindings": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" + }, + "bip39": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-2.5.0.tgz", + "integrity": "sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA==", + "requires": { + "create-hash": "^1.1.0", + "pbkdf2": "^3.0.9", + "randombytes": "^2.0.1", + "safe-buffer": "^5.0.1", + "unorm": "^1.3.3" + } + }, + "bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "bluebird": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", @@ -1391,8 +1467,7 @@ "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" }, "brace-expansion": { "version": "1.1.11", @@ -1436,8 +1511,7 @@ "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, "browser-stdout": { "version": "1.3.1", @@ -1449,7 +1523,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, "requires": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -1527,6 +1600,24 @@ "node-releases": "^1.0.0-alpha.11" } }, + "bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "requires": { + "base-x": "^3.0.2" + } + }, + "bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "requires": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", @@ -1547,8 +1638,7 @@ "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, "builtin-modules": { "version": "1.1.1", @@ -1704,7 +1794,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -1788,6 +1877,22 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, + "coinstring": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/coinstring/-/coinstring-2.3.0.tgz", + "integrity": "sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q=", + "requires": { + "bs58": "^2.0.1", + "create-hash": "^1.1.1" + }, + "dependencies": { + "bs58": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-2.0.1.tgz", + "integrity": "sha1-VZCNWPGYKrogCPob7Y+RmYopv40=" + } + } + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -1922,7 +2027,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, "requires": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -1935,7 +2039,6 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, "requires": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -2167,6 +2270,16 @@ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, + "drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "requires": { + "browserify-aes": "^1.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" + } + }, "duplexify": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", @@ -2189,7 +2302,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", - "dev": true, "requires": { "bn.js": "^4.4.0", "brorand": "^1.0.1", @@ -2402,6 +2514,12 @@ } } }, + "eslint-plugin-chai-friendly": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-chai-friendly/-/eslint-plugin-chai-friendly-0.4.1.tgz", + "integrity": "sha512-hkpLN7VVoGGsofZjUhcQ+sufC3FgqMJwD0DvAcRfxY1tVRyQyVsqpaKnToPHJQOrRo0FQ0fSEDwW2gr4rsNdGA==", + "dev": true + }, "eslint-plugin-es": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.3.1.tgz", @@ -2545,6 +2663,44 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "^0.1.3", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + }, + "ethereumjs-wallet": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.2.tgz", + "integrity": "sha512-DHEKPV9lYORM7dL8602dkb+AgdfzCYz2lxpdYQoD3OwG355LLDuivW9rGuLpDMCry/ORyBYV6n+QCo/71SwACg==", + "requires": { + "aes-js": "^3.1.1", + "bs58check": "^2.1.2", + "ethereumjs-util": "^5.2.0", + "hdkey": "^1.0.0", + "safe-buffer": "^5.1.2", + "scrypt.js": "^0.2.0", + "utf8": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, "events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", @@ -2555,7 +2711,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, "requires": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -3563,7 +3718,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -3573,12 +3727,21 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", - "dev": true, "requires": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" } }, + "hdkey": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-1.1.0.tgz", + "integrity": "sha512-E7aU8pNlWUJbXGjTz/+lKf1LkMcA3hUrC5ZleeizrmLSd++kvf8mSOe3q8CmBDA9j4hdfXO5iY6hGiTUCOV2jQ==", + "requires": { + "coinstring": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", @@ -3589,7 +3752,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, "requires": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -3670,8 +3832,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "inquirer": { "version": "6.2.0", @@ -3889,6 +4050,11 @@ "is-extglob": "^2.1.1" } }, + "is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -4045,6 +4211,17 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, + "keccak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "requires": { + "bindings": "^1.2.1", + "inherits": "^2.0.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" + } + }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", @@ -4188,7 +4365,6 @@ "version": "1.3.4", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", - "dev": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -4253,14 +4429,12 @@ "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, "minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, "minimatch": { "version": "3.0.4", @@ -4487,9 +4661,7 @@ "nan": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.0.tgz", - "integrity": "sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw==", - "dev": true, - "optional": true + "integrity": "sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw==" }, "nanomatch": { "version": "1.2.13", @@ -4880,7 +5052,6 @@ "version": "3.0.16", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", - "dev": true, "requires": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -5041,7 +5212,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true, "requires": { "safe-buffer": "^5.1.0" } @@ -5311,12 +5481,19 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1" } }, + "rlp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.1.0.tgz", + "integrity": "sha512-93U7IKH5j7nmXFVg19MeNBGzQW5uXW1pmCuKY8veeKIhYTE32C2d0mOegfiIAfXcHOKJjjPlJisn8iHDF5AezA==", + "requires": { + "safe-buffer": "^5.1.1" + } + }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -5347,8 +5524,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safe-regex": { "version": "1.1.0", @@ -5375,6 +5551,46 @@ "ajv-keywords": "^3.1.0" } }, + "scrypt": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz", + "integrity": "sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0=", + "requires": { + "nan": "^2.0.8" + } + }, + "scrypt.js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.2.0.tgz", + "integrity": "sha1-r40UZbcemZARC+38WTuUeeA6ito=", + "requires": { + "scrypt": "^6.0.2", + "scryptsy": "^1.2.1" + } + }, + "scryptsy": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", + "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", + "requires": { + "pbkdf2": "^3.0.3" + } + }, + "secp256k1": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.5.2.tgz", + "integrity": "sha512-iin3kojdybY6NArd+UFsoTuapOF7bnJNf2UbcWXaY3z+E1sJDipl60vtzB5hbO/uquBu7z0fd4VC4Irp+xoFVQ==", + "requires": { + "bindings": "^1.2.1", + "bip66": "^1.1.3", + "bn.js": "^4.11.3", + "create-hash": "^1.1.2", + "drbg.js": "^1.0.1", + "elliptic": "^6.2.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" + } + }, "semver": { "version": "5.5.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", @@ -5432,7 +5648,6 @@ "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -5803,6 +6018,14 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, + "strip-hex-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", + "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -6094,6 +6317,11 @@ "imurmurhash": "^0.1.4" } }, + "unorm": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.4.1.tgz", + "integrity": "sha1-NkIA1fE2RsqLzURJAnEzVhR5IwA=" + }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -6179,6 +6407,11 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, + "utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==" + }, "util": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", @@ -6204,6 +6437,11 @@ "object.getownpropertydescriptors": "^2.0.3" } }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, "v8-compile-cache": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz", @@ -6323,6 +6561,12 @@ } } }, + "webpack-node-externals": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-1.7.2.tgz", + "integrity": "sha512-ajerHZ+BJKeCLviLUUmnyd5B4RavLF76uv3cs6KNuO8W+HuQaEs0y0L7o40NQxdPy5w0pcv8Ew7yPUAQG0UdCg==", + "dev": true + }, "webpack-sources": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", diff --git a/package.json b/package.json index 9544477..fd664c3 100644 --- a/package.json +++ b/package.json @@ -12,12 +12,16 @@ "author": "Chaintope Inc.", "devDependencies": { "@babel/core": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/polyfill": "^7.0.0", "@babel/preset-env": "^7.0.0", + "@babel/runtime": "^7.0.0", "babel-eslint": "^9.0.0", "babel-loader": "^8.0.2", "chai": "^4.1.2", "eslint": "^5.5.0", "eslint-config-standard": "^12.0.0", + "eslint-plugin-chai-friendly": "^0.4.1", "eslint-plugin-import": "^2.14.0", "eslint-plugin-mocha": "^5.2.0", "eslint-plugin-node": "^7.0.1", @@ -26,6 +30,11 @@ "mocha": "^5.2.0", "mocha-webpack": "^2.0.0-beta.0", "webpack": "^4.17.1", - "webpack-cli": "^3.1.0" + "webpack-cli": "^3.1.0", + "webpack-node-externals": "^1.7.2" + }, + "dependencies": { + "bip39": "^2.5.0", + "ethereumjs-wallet": "^0.6.2" } } diff --git a/test/masa.spec.js b/test/masa.spec.js index 2be41fc..c2ad5c2 100644 --- a/test/masa.spec.js +++ b/test/masa.spec.js @@ -1,9 +1,35 @@ import masa from '../lib/masa' -var assert = require('assert') +import { expect } from 'chai' describe('masa.js', () => { - it('should load', () => { - console.log(masa) - assert(masa) + describe('init', () => { + it('should load', () => { + expect(masa).to.be.ok + }) + }) + describe('masa point', () => { + it('get masa point amount', async() => { + expect(await masa.point.amountOf('0xaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbb')).to.be.equal(500) + expect(await masa.point.amountOf('0x6861766520636f696e20697300000000000000b8')).to.be.equal(200) + }) + it('get community masa point amount', async() => { + expect(await masa.point.communityAmountOf('0x6861766520636f696e20697300000000000000b8', 5)).to.be.equal(200) + }) + it('masa.point.feedback is not support.', () => { + expect(function() { + masa.point.feedback('0x6861766520636f696e20697300000000000000b8', 'Challenge Caravan', 1, '') + }).to.throw('Not support function. Please use MasaTx.') + }) + }) + describe('masa coin', () => { + it('balanceOf', async() => { + const balance = await masa.coin.balanceOf('0xdaF8F49A3671082ED2ab0b67ecB7f0182fAEAb6C') + return expect(balance).to.be.equal(100) + }) + it('unsupport transfer.', () => { + expect(function() { + masa.coin.transfer('0xdaF8F49A3671082ED2ab0b67ecB7f0182fAEAb6C', 20) + }).to.throw('Not support function. Please use MasaTx.') + }) }) }) diff --git a/test/masa_tx.spec.js b/test/masa_tx.spec.js new file mode 100644 index 0000000..dd7256e --- /dev/null +++ b/test/masa_tx.spec.js @@ -0,0 +1,71 @@ +import { expect } from 'chai' +import MasaTx from '../lib/masa_tx' +import { GANACHE_MNEMONIC } from './util' + +describe('MasaTx', () => { + describe('init', () => { + it('should load', () => { + expect(MasaTx).to.be.ok + }) + it('create with generate Wallet', () => { + const masaTx = new MasaTx() + expect(masaTx).to.be.ok + expect(masaTx.wallet.mnemonic).to.be.a('string') + expect(masaTx.wallet.mnemonic).to.be.not.equal(GANACHE_MNEMONIC) + }) + it('create with restore Wallet', () => { + const masaTx = new MasaTx(GANACHE_MNEMONIC) + expect(masaTx).to.be.ok + expect(masaTx.wallet.mnemonic).to.be.a('string') + expect(masaTx.wallet.mnemonic).to.be.equal(GANACHE_MNEMONIC) + }) + }) + describe('masaPoint', () => { + let masaTx + beforeEach(() => { + masaTx = new MasaTx() + }) + it('create feedback transaction', async() => { + const feedbackTx = await masaTx.point.feedback('0xdaF8F49A3671082ED2ab0b67ecB7f0182fAEAb6C', 'Challenge Caravan', 1, '') + expect(feedbackTx).to.be.a('transaction') + }) + it('unsupport amountOf', () => { + expect(function() { + masaTx.point.amountOf('0x6861766520636f696e20697300000000000000b8') + }).to.throw('Not support function. Please use Masa.') + }) + it('unsupport communityAmountOf', () => { + expect(function() { + masaTx.point.communityAmountOf('0x6861766520636f696e20697300000000000000b8', 'chare cara') + }).to.throw('Not support function. Please use Masa.') + }) + }) + describe('masaCoin', () => { + let masaTx + beforeEach(() => { + masaTx = new MasaTx() + }) + it('create transfer transaction', async() => { + const transferTx = await masaTx.coin.transfer('0xdaF8F49A3671082ED2ab0b67ecB7f0182fAEAb6C', 100) + expect(transferTx).to.be.a('transaction') + }) + it('unsupport balanceOf', () => { + return masaTx.coin + .balanceOf('0xdaF8F49A3671082ED2ab0b67ecB7f0182fAEAb6C').then(balance => { + expect.fail('not happend error') + }).catch(e => { + expect(e.message).to.be.equal('Not support function. Please use Masa.') + }) + }) + }) + describe('community', () => { + let masaTx + beforeEach(() => { + masaTx = new MasaTx() + }) + it('create create transaction', async() => { + const createTx = await masaTx.community.create('SDGs') + expect(createTx).to.be.a('transaction') + }) + }) +}) diff --git a/test/util.js b/test/util.js new file mode 100644 index 0000000..791aadd --- /dev/null +++ b/test/util.js @@ -0,0 +1,5 @@ +const GANACHE_MNEMONIC = 'special client interest guess wrist bring rack hockey tip divert three toe' + +export { + GANACHE_MNEMONIC +} diff --git a/test/wallet.spec.js b/test/wallet.spec.js new file mode 100644 index 0000000..ee5dea6 --- /dev/null +++ b/test/wallet.spec.js @@ -0,0 +1,51 @@ +import Wallet from '../lib/wallet' +import { expect } from 'chai' +import { GANACHE_MNEMONIC } from './util' + +describe('wallet.js', () => { + it('should load', () => { + expect(Wallet).to.be.ok + }) + describe('initialize', function() { + it('generate mnemonic', () => { + const mnemonic = Wallet.generateMnemonic() + expect(mnemonic).to.be.a('string') + expect(mnemonic.split(' ')).to.have.lengthOf(12) + }) + it('create wallet', function() { + this.timeout(10000) + const wallet = new Wallet(GANACHE_MNEMONIC) + expect(wallet).to.be.ok + expect(wallet).to.be.a('wallet') + }) + it('failed. if specify undefined', () => { + expect(function() { + return new Wallet(undefined) + }).to.throw('invalid mnemonic!') + }) + it('failed. if specify empty string', () => { + expect(function() { + return new Wallet('') + }).to.throw('invalid mnemonic!') + }) + }) + describe('wallet functions', function() { + this.timeout(10000) + let wallet + before(function() { + wallet = new Wallet(GANACHE_MNEMONIC) + }) + it('check cat reget mnemonic', () => { + expect(wallet.mnemonic).to.be.equal(GANACHE_MNEMONIC) + }) + it('check privateKey', () => { + expect(wallet.privateKey.toString('hex')).to.be.equal('4d8d0ece9fd220f7fb7f53f71e636ac377aa8bab4e5c8e601e515a625917134e') + }) + it('check publicKey', () => { + expect(wallet.publicKey.toString('hex')).to.be.equal('06d40dcd8748c724e20405eb837a6fc02eea32492dbea17b852ae1dba8500ba1193d843bb694f8d0fafab4007f213607a85297ebf505b2e9a1708b6d3af25553') + }) + it('check address', () => { + expect(wallet.address).to.be.equal('0xdaf8f49a3671082ed2ab0b67ecb7f0182faeab6c') + }) + }) +}) diff --git a/webpack.config.js b/webpack.config.js index 0f67bb0..220f91c 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,7 +1,10 @@ -const path = require('path'); +const path = require('path') +const nodeExternals = require('webpack-node-externals') module.exports = { - entry: './index.js', + target: 'node', + externals: [nodeExternals()], + entry: ['./index.js'], mode: 'development', output: { filename: 'masa.js', @@ -13,12 +16,13 @@ module.exports = { test: /\.js$/, exclude: /node_modules/, use: { - loader: "babel-loader", + loader: 'babel-loader', options: { - presets: ['@babel/preset-env'] + presets: ['@babel/preset-env'], + plugins: ['@babel/transform-runtime'] } } } ] } -}; +}