diff --git a/src/.gitignore b/src/.gitignore index 074ab52..8ef3c88 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,2 +1,3 @@ package-lock.json -node_modules \ No newline at end of file +node_modules +build \ No newline at end of file diff --git a/src/ERC20/contracts/Migrations.sol b/src/ERC20/contracts/Migrations.sol new file mode 100644 index 0000000..c378ffb --- /dev/null +++ b/src/ERC20/contracts/Migrations.sol @@ -0,0 +1,23 @@ +pragma solidity >=0.4.21 <0.6.0; + +contract Migrations { + address public owner; + uint public last_completed_migration; + + constructor() public { + owner = msg.sender; + } + + modifier restricted() { + if (msg.sender == owner) _; + } + + function setCompleted(uint completed) public restricted { + last_completed_migration = completed; + } + + function upgrade(address new_address) public restricted { + Migrations upgraded = Migrations(new_address); + upgraded.setCompleted(last_completed_migration); + } +} diff --git a/src/ERC20/contracts/erc20/ERC20.sol b/src/ERC20/contracts/erc20/ERC20.sol new file mode 100644 index 0000000..ace5169 --- /dev/null +++ b/src/ERC20/contracts/erc20/ERC20.sol @@ -0,0 +1,73 @@ +/* +Implements EIP20 token standard: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md +.*/ + + +pragma solidity ^0.5.0; + +import "./ERC20Interface.sol"; + + +contract ERC20 is ERC20Interface { + + uint256 constant private MAX_UINT256 = 2**256 - 1; + mapping (address => uint256) public balances; + mapping (address => mapping (address => uint256)) public allowed; + /* + NOTE: + The following variables are OPTIONAL vanities. One does not have to include them. + They allow one to customise the token contract & in no way influences the core functionality. + Some wallets/interfaces might not even bother to look at this information. + */ + string public name; //fancy name: eg Simon Bucks + uint8 public decimals; //How many decimals to show. + string public symbol; //An identifier: eg SBX + uint256 public totalSupply; + + constructor( + uint256 _initialAmount, + string memory _tokenName, + uint8 _decimalUnits, + string memory _tokenSymbol + ) public { + balances[msg.sender] = _initialAmount; // Give the creator all initial tokens + totalSupply = _initialAmount; // Update total supply + name = _tokenName; // Set the name for display purposes + decimals = _decimalUnits; // Amount of decimals for display purposes + symbol = _tokenSymbol; // Set the symbol for display purposes + } + + function transfer(address _to, uint256 _value) public returns (bool success) { + require(balances[msg.sender] >= _value); + balances[msg.sender] -= _value; + balances[_to] += _value; + emit Transfer(msg.sender, _to, _value); //solhint-disable-line indent, no-unused-vars + return true; + } + + function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { + uint256 allowance = allowed[_from][msg.sender]; + require(balances[_from] >= _value && allowance >= _value); + balances[_to] += _value; + balances[_from] -= _value; + if (allowance < MAX_UINT256) { + allowed[_from][msg.sender] -= _value; + } + emit Transfer(_from, _to, _value); //solhint-disable-line indent, no-unused-vars + return true; + } + + function balanceOf(address _owner) public view returns (uint256 balance) { + return balances[_owner]; + } + + function approve(address _spender, uint256 _value) public returns (bool success) { + allowed[msg.sender][_spender] = _value; + emit Approval(msg.sender, _spender, _value); //solhint-disable-line indent, no-unused-vars + return true; + } + + function allowance(address _owner, address _spender) public view returns (uint256 remaining) { + return allowed[_owner][_spender]; + } +} \ No newline at end of file diff --git a/src/ERC20/contracts/erc20/ERC20Interface.sol b/src/ERC20/contracts/erc20/ERC20Interface.sol new file mode 100644 index 0000000..8951a25 --- /dev/null +++ b/src/ERC20/contracts/erc20/ERC20Interface.sol @@ -0,0 +1,50 @@ +// Abstract contract for the full ERC 20 Token standard +// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md +pragma solidity ^0.5.0; + + +contract ERC20Interface { + /* This is a slight change to the ERC20 base standard. + function totalSupply() constant returns (uint256 supply); + is replaced with: + uint256 public totalSupply; + This automatically creates a getter function for the totalSupply. + This is moved to the base contract since public getter functions are not + currently recognised as an implementation of the matching abstract + function by the compiler. + */ + /// total amount of tokens + uint256 public totalSupply; + + /// @param _owner The address from which the balance will be retrieved + /// @return The balance + function balanceOf(address _owner) public view returns (uint256 balance); + + /// @notice send `_value` token to `_to` from `msg.sender` + /// @param _to The address of the recipient + /// @param _value The amount of token to be transferred + /// @return Whether the transfer was successful or not + function transfer(address _to, uint256 _value) public returns (bool success); + + /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` + /// @param _from The address of the sender + /// @param _to The address of the recipient + /// @param _value The amount of token to be transferred + /// @return Whether the transfer was successful or not + function transferFrom(address _from, address _to, uint256 _value) public returns (bool success); + + /// @notice `msg.sender` approves `_spender` to spend `_value` tokens + /// @param _spender The address of the account able to transfer the tokens + /// @param _value The amount of tokens to be approved for transfer + /// @return Whether the approval was successful or not + function approve(address _spender, uint256 _value) public returns (bool success); + + /// @param _owner The address of the account owning tokens + /// @param _spender The address of the account able to transfer the tokens + /// @return Amount of remaining tokens allowed to spent + function allowance(address _owner, address _spender) public view returns (uint256 remaining); + + // solhint-disable-next-line no-simple-event-func-name + event Transfer(address indexed _from, address indexed _to, uint256 _value); + event Approval(address indexed _owner, address indexed _spender, uint256 _value); +} \ No newline at end of file diff --git a/src/ERC20/migrations/1_initial_migration.js b/src/ERC20/migrations/1_initial_migration.js new file mode 100644 index 0000000..145cfb9 --- /dev/null +++ b/src/ERC20/migrations/1_initial_migration.js @@ -0,0 +1,5 @@ +const Migrations = artifacts.require("Migrations"); + +module.exports = function (deployer) { + deployer.deploy(Migrations); +}; diff --git a/src/ERC20/migrations/2_deploy_tokens.js b/src/ERC20/migrations/2_deploy_tokens.js new file mode 100644 index 0000000..0b1fcb7 --- /dev/null +++ b/src/ERC20/migrations/2_deploy_tokens.js @@ -0,0 +1,5 @@ +const ERC20 = artifacts.require("ERC20"); + +module.exports = (deployer) => { + deployer.deploy(ERC20, 10000, 'Simon Bucks', 1, 'SBX'); +}; diff --git a/src/ERC20/test/erc20.js b/src/ERC20/test/erc20.js new file mode 100644 index 0000000..b8fefba --- /dev/null +++ b/src/ERC20/test/erc20.js @@ -0,0 +1,221 @@ +"use strict"; + +let assertRevert = async (promise) => { + try { + await promise; + } catch (error) { + const revertFound = error.message.search('revert') >= 0; + assert(revertFound, `Expected "revert", got ${error} instead`); + return; + } + assert.fail('Expected revert not received'); +}; + +const ERC20Abstraction = artifacts.require('ERC20'); +let HST; + +contract('ERC20', (accounts) => { + beforeEach(async () => { + HST = await ERC20Abstraction.new(10000, 'Simon Bucks', 1, 'SBX', { from: accounts[0] }); + }); + + it('creation: should create an initial balance of 10000 for the creator', async () => { + const balance = await HST.balanceOf.call(accounts[0]); + assert.strictEqual(balance.toNumber(), 10000); + }); + + it('creation: test correct setting of vanity information', async () => { + const name = await HST.name.call(); + assert.strictEqual(name, 'Simon Bucks'); + + const decimals = await HST.decimals.call(); + assert.strictEqual(decimals.toNumber(), 1); + + const symbol = await HST.symbol.call(); + assert.strictEqual(symbol, 'SBX'); + }); + + it.skip('creation: should succeed in creating over 2^256 - 1 (max) tokens', async () => { + // 2^256 - 1 + const HST2 = await ERC20Abstraction.new('115792089237316195423570985008687907853269984665640564039457584007913129639935', 'Simon Bucks', 1, 'SBX', { from: accounts[0] }); + const totalSupply = await HST2.totalSupply(); + const match = totalSupply.equals('1.15792089237316195423570985008687907853269984665640564039457584007913129639935e+77'); + assert(match, 'result is not correct'); + }); + + // TRANSERS + // normal transfers without approvals + it('transfers: ether transfer should be reversed.', async () => { + const balanceBefore = await HST.balanceOf.call(accounts[0]); + assert.strictEqual(balanceBefore.toNumber(), 10000); + + await assertRevert(new Promise((resolve, reject) => { + web3.eth.sendTransaction({ from: accounts[0], to: HST.address, value: web3.utils.toWei('10', 'Ether') }, (err, res) => { + if (err) { reject(err); } + resolve(res); + }); + })); + + const balanceAfter = await HST.balanceOf.call(accounts[0]); + assert.strictEqual(balanceAfter.toNumber(), 10000); + }); + + it('transfers: should transfer 10000 to accounts[1] with accounts[0] having 10000', async () => { + await HST.transfer(accounts[1], 10000, { from: accounts[0] }); + const balance = await HST.balanceOf.call(accounts[1]); + assert.strictEqual(balance.toNumber(), 10000); + }); + + it('transfers: should fail when trying to transfer 10001 to accounts[1] with accounts[0] having 10000', async () => { + await assertRevert(HST.transfer.call(accounts[1], 10001, { from: accounts[0] })); + }); + + it('transfers: should handle zero-transfers normally', async () => { + assert(await HST.transfer.call(accounts[1], 0, { from: accounts[0] }), 'zero-transfer has failed'); + }); + + // NOTE: testing uint256 wrapping is impossible since you can't supply > 2^256 -1 + // todo: transfer max amounts + + // APPROVALS + it('approvals: msg.sender should approve 100 to accounts[1]', async () => { + await HST.approve(accounts[1], 100, { from: accounts[0] }); + const allowance = await HST.allowance.call(accounts[0], accounts[1]); + assert.strictEqual(allowance.toNumber(), 100); + }); + + // bit overkill. But is for testing a bug + it('approvals: msg.sender approves accounts[1] of 100 & withdraws 20 once.', async () => { + const balance0 = await HST.balanceOf.call(accounts[0]); + assert.strictEqual(balance0.toNumber(), 10000); + + await HST.approve(accounts[1], 100, { from: accounts[0] }); // 100 + const balance2 = await HST.balanceOf.call(accounts[2]); + assert.strictEqual(balance2.toNumber(), 0, 'balance2 not correct'); + + await HST.transferFrom.call(accounts[0], accounts[2], 20, { from: accounts[1] }); + await HST.allowance.call(accounts[0], accounts[1]); + await HST.transferFrom(accounts[0], accounts[2], 20, { from: accounts[1] }); // -20 + const allowance01 = await HST.allowance.call(accounts[0], accounts[1]); + assert.strictEqual(allowance01.toNumber(), 80); // =80 + + const balance22 = await HST.balanceOf.call(accounts[2]); + assert.strictEqual(balance22.toNumber(), 20); + + const balance02 = await HST.balanceOf.call(accounts[0]); + assert.strictEqual(balance02.toNumber(), 9980); + }); + + // should approve 100 of msg.sender & withdraw 50, twice. (should succeed) + it('approvals: msg.sender approves accounts[1] of 100 & withdraws 20 twice.', async () => { + await HST.approve(accounts[1], 100, { from: accounts[0] }); + const allowance01 = await HST.allowance.call(accounts[0], accounts[1]); + assert.strictEqual(allowance01.toNumber(), 100); + + await HST.transferFrom(accounts[0], accounts[2], 20, { from: accounts[1] }); + const allowance012 = await HST.allowance.call(accounts[0], accounts[1]); + assert.strictEqual(allowance012.toNumber(), 80); + + const balance2 = await HST.balanceOf.call(accounts[2]); + assert.strictEqual(balance2.toNumber(), 20); + + const balance0 = await HST.balanceOf.call(accounts[0]); + assert.strictEqual(balance0.toNumber(), 9980); + + // FIRST tx done. + // onto next. + await HST.transferFrom(accounts[0], accounts[2], 20, { from: accounts[1] }); + const allowance013 = await HST.allowance.call(accounts[0], accounts[1]); + assert.strictEqual(allowance013.toNumber(), 60); + + const balance22 = await HST.balanceOf.call(accounts[2]); + assert.strictEqual(balance22.toNumber(), 40); + + const balance02 = await HST.balanceOf.call(accounts[0]); + assert.strictEqual(balance02.toNumber(), 9960); + }); + + // should approve 100 of msg.sender & withdraw 50 & 60 (should fail). + it('approvals: msg.sender approves accounts[1] of 100 & withdraws 50 & 60 (2nd tx should fail)', async () => { + await HST.approve(accounts[1], 100, { from: accounts[0] }); + const allowance01 = await HST.allowance.call(accounts[0], accounts[1]); + assert.strictEqual(allowance01.toNumber(), 100); + + await HST.transferFrom(accounts[0], accounts[2], 50, { from: accounts[1] }); + const allowance012 = await HST.allowance.call(accounts[0], accounts[1]); + assert.strictEqual(allowance012.toNumber(), 50); + + const balance2 = await HST.balanceOf.call(accounts[2]); + assert.strictEqual(balance2.toNumber(), 50); + + const balance0 = await HST.balanceOf.call(accounts[0]); + assert.strictEqual(balance0.toNumber(), 9950); + + // FIRST tx done. + // onto next. + await assertRevert(HST.transferFrom.call(accounts[0], accounts[2], 60, { from: accounts[1] })); + }); + + it('approvals: attempt withdrawal from account with no allowance (should fail)', async () => { + await assertRevert(HST.transferFrom.call(accounts[0], accounts[2], 60, { from: accounts[1] })); + }); + + it('approvals: allow accounts[1] 100 to withdraw from accounts[0]. Withdraw 60 and then approve 0 & attempt transfer.', async () => { + await HST.approve(accounts[1], 100, { from: accounts[0] }); + await HST.transferFrom(accounts[0], accounts[2], 60, { from: accounts[1] }); + await HST.approve(accounts[1], 0, { from: accounts[0] }); + await assertRevert(HST.transferFrom.call(accounts[0], accounts[2], 10, { from: accounts[1] })); + }); + + it.skip('approvals: approve max (2^256 - 1)', async () => { + await HST.approve(accounts[1], '115792089237316195423570985008687907853269984665640564039457584007913129639935', { from: accounts[0] }); + const allowance = await HST.allowance(accounts[0], accounts[1]); + assert(allowance.equals('1.15792089237316195423570985008687907853269984665640564039457584007913129639935e+77')); + }); + + // should approve max of msg.sender & withdraw 20 without changing allowance (should succeed). + it.skip('approvals: msg.sender approves accounts[1] of max (2^256 - 1) & withdraws 20', async () => { + const balance0 = await HST.balanceOf.call(accounts[0]); + assert.strictEqual(balance0.toNumber(), 10000); + + const max = '1.15792089237316195423570985008687907853269984665640564039457584007913129639935e+77'; + await HST.approve(accounts[1], max, { from: accounts[0] }); + const balance2 = await HST.balanceOf.call(accounts[2]); + assert.strictEqual(balance2.toNumber(), 0, 'balance2 not correct'); + + await HST.transferFrom(accounts[0], accounts[2], 20, { from: accounts[1] }); + const allowance01 = await HST.allowance.call(accounts[0], accounts[1]); + assert(allowance01.equals(max)); + + const balance22 = await HST.balanceOf.call(accounts[2]); + assert.strictEqual(balance22.toNumber(), 20); + + const balance02 = await HST.balanceOf.call(accounts[0]); + assert.strictEqual(balance02.toNumber(), 9980); + }); + + /* eslint-disable no-underscore-dangle */ + it('events: should fire Transfer event properly', async () => { + const res = await HST.transfer(accounts[1], '2666', { from: accounts[0] }); + const transferLog = res.logs.find(element => element.event.match('Transfer')); + assert.strictEqual(transferLog.args._from, accounts[0]); + assert.strictEqual(transferLog.args._to, accounts[1]); + assert.strictEqual(transferLog.args._value.toString(), '2666'); + }); + + it('events: should fire Transfer event normally on a zero transfer', async () => { + const res = await HST.transfer(accounts[1], '0', { from: accounts[0] }); + const transferLog = res.logs.find(element => element.event.match('Transfer')); + assert.strictEqual(transferLog.args._from, accounts[0]); + assert.strictEqual(transferLog.args._to, accounts[1]); + assert.strictEqual(transferLog.args._value.toString(), '0'); + }); + + it('events: should fire Approval event properly', async () => { + const res = await HST.approve(accounts[1], '2666', { from: accounts[0] }); + const approvalLog = res.logs.find(element => element.event.match('Approval')); + assert.strictEqual(approvalLog.args._owner, accounts[0]); + assert.strictEqual(approvalLog.args._spender, accounts[1]); + assert.strictEqual(approvalLog.args._value.toString(), '2666'); + }); +}); diff --git a/src/ERC20/truffle-config.js b/src/ERC20/truffle-config.js new file mode 100644 index 0000000..eacef21 --- /dev/null +++ b/src/ERC20/truffle-config.js @@ -0,0 +1,100 @@ +/** + * Use this file to configure your truffle project. It's seeded with some + * common settings for different networks and features like migrations, + * compilation and testing. Uncomment the ones you need or modify + * them to suit your project as necessary. + * + * More information about configuration can be found at: + * + * truffleframework.com/docs/advanced/configuration + * + * To deploy via Infura you'll need a wallet provider (like truffle-hdwallet-provider) + * to sign your transactions before they're sent to a remote public node. Infura accounts + * are available for free at: infura.io/register. + * + * You'll also need a mnemonic - the twelve word phrase the wallet uses to generate + * public/private key pairs. If you're publishing your code to GitHub make sure you load this + * phrase from a file you've .gitignored so it doesn't accidentally become public. + * + */ + +// const HDWalletProvider = require('truffle-hdwallet-provider'); +// const infuraKey = "fj4jll3k....."; +// +// const fs = require('fs'); +// const mnemonic = fs.readFileSync(".secret").toString().trim(); + +module.exports = { + + /** + * Networks define how you connect to your ethereum client and let you set the + * defaults web3 uses to send transactions. If you don't specify one truffle + * will spin up a development blockchain for you on port 9545 when you + * run `develop` or `test`. You can ask a truffle command to use a specific + * network from the command line, e.g + * + * $ truffle test --network + */ + + networks: { + // Useful for testing. The `development` name is special - truffle uses it by default + // if it's defined here and no other network is specified at the command line. + // You should run a client (like ganache-cli, geth or parity) in a separate terminal + // tab if you use this network and you must also set the `host`, `port` and `network_id` + // options below to some value. + // + development: { + host: "127.0.0.1", // Localhost (default: none) + port: 8545, // Standard Ethereum port (default: none) + network_id: "*", // Any network (default: none) + }, + + // Another network with more advanced options... + // advanced: { + // port: 8777, // Custom port + // network_id: 1342, // Custom network + // gas: 8500000, // Gas sent with each transaction (default: ~6700000) + // gasPrice: 20000000000, // 20 gwei (in wei) (default: 100 gwei) + // from:
, // Account to send txs from (default: accounts[0]) + // websockets: true // Enable EventEmitter interface for web3 (default: false) + // }, + + // Useful for deploying to a public network. + // NB: It's important to wrap the provider as a function. + // ropsten: { + // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`), + // network_id: 3, // Ropsten's id + // gas: 5500000, // Ropsten has a lower block limit than mainnet + // confirmations: 2, // # of confs to wait between deployments. (default: 0) + // timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) + // skipDryRun: true // Skip dry run before migrations? (default: false for public nets ) + // }, + + // Useful for private networks + // private: { + // provider: () => new HDWalletProvider(mnemonic, `https://network.io`), + // network_id: 2111, // This network is yours, in the cloud. + // production: true // Treats this network as if it was a public net. (default: false) + // } + }, + + // Set default mocha options here, use special reporters etc. + mocha: { + // timeout: 100000 + }, + + // Configure your compilers + compilers: { + solc: { + // version: "0.5.1", // Fetch exact version from solc-bin (default: truffle's version) + // docker: true, // Use "0.5.1" you've installed locally with docker (default: false) + // settings: { // See the solidity docs for advice about optimization and evmVersion + // optimizer: { + // enabled: false, + // runs: 200 + // }, + // evmVersion: "byzantium" + // } + } + } +}; diff --git a/src/js/Readme.md b/src/basic_chain/js/Readme.md similarity index 79% rename from src/js/Readme.md rename to src/basic_chain/js/Readme.md index 12618e0..eecbda1 100644 --- a/src/js/Readme.md +++ b/src/basic_chain/js/Readme.md @@ -1,6 +1,6 @@ # BlockChain for Node.js -Basic implementation for blockchain in node.js +Basic implementation for blockchain in Node.js - [x] Block structure - [x] Blockchain structure diff --git a/src/js/account.js b/src/basic_chain/js/account.js similarity index 100% rename from src/js/account.js rename to src/basic_chain/js/account.js diff --git a/src/js/block.js b/src/basic_chain/js/block.js similarity index 100% rename from src/js/block.js rename to src/basic_chain/js/block.js diff --git a/src/js/blockchain.js b/src/basic_chain/js/blockchain.js similarity index 100% rename from src/js/blockchain.js rename to src/basic_chain/js/blockchain.js diff --git a/src/js/consensus/dpos.js b/src/basic_chain/js/consensus/dpos.js similarity index 100% rename from src/js/consensus/dpos.js rename to src/basic_chain/js/consensus/dpos.js diff --git a/src/js/consensus/pbft.js b/src/basic_chain/js/consensus/pbft.js similarity index 100% rename from src/js/consensus/pbft.js rename to src/basic_chain/js/consensus/pbft.js diff --git a/src/js/consensus/peercoin.cc b/src/basic_chain/js/consensus/peercoin.cc similarity index 100% rename from src/js/consensus/peercoin.cc rename to src/basic_chain/js/consensus/peercoin.cc diff --git a/src/js/consensus/pos.js b/src/basic_chain/js/consensus/pos.js similarity index 100% rename from src/js/consensus/pos.js rename to src/basic_chain/js/consensus/pos.js diff --git a/src/js/consensus/pow.js b/src/basic_chain/js/consensus/pow.js similarity index 100% rename from src/js/consensus/pow.js rename to src/basic_chain/js/consensus/pow.js diff --git a/src/js/consensus/slot.js b/src/basic_chain/js/consensus/slot.js similarity index 100% rename from src/js/consensus/slot.js rename to src/basic_chain/js/consensus/slot.js diff --git a/src/js/crypto.js b/src/basic_chain/js/crypto.js similarity index 100% rename from src/js/crypto.js rename to src/basic_chain/js/crypto.js diff --git a/src/js/genesis_block.json b/src/basic_chain/js/genesis_block.json similarity index 100% rename from src/js/genesis_block.json rename to src/basic_chain/js/genesis_block.json diff --git a/src/js/message.js b/src/basic_chain/js/message.js similarity index 100% rename from src/js/message.js rename to src/basic_chain/js/message.js diff --git a/src/js/network.js b/src/basic_chain/js/network.js similarity index 100% rename from src/js/network.js rename to src/basic_chain/js/network.js diff --git a/src/js/package.json b/src/basic_chain/js/package.json similarity index 100% rename from src/js/package.json rename to src/basic_chain/js/package.json diff --git a/src/js/test/create_block.js b/src/basic_chain/js/test/create_block.js similarity index 100% rename from src/js/test/create_block.js rename to src/basic_chain/js/test/create_block.js diff --git a/src/js/test/create_genesis.js b/src/basic_chain/js/test/create_genesis.js similarity index 100% rename from src/js/test/create_genesis.js rename to src/basic_chain/js/test/create_genesis.js diff --git a/src/js/test/db.js b/src/basic_chain/js/test/db.js similarity index 100% rename from src/js/test/db.js rename to src/basic_chain/js/test/db.js diff --git a/src/js/test/dpos.js b/src/basic_chain/js/test/dpos.js similarity index 100% rename from src/js/test/dpos.js rename to src/basic_chain/js/test/dpos.js diff --git a/src/js/test/dpos_pbft.js b/src/basic_chain/js/test/dpos_pbft.js similarity index 100% rename from src/js/test/dpos_pbft.js rename to src/basic_chain/js/test/dpos_pbft.js diff --git a/src/js/test/network.js b/src/basic_chain/js/test/network.js similarity index 100% rename from src/js/test/network.js rename to src/basic_chain/js/test/network.js diff --git a/src/js/test/pow.js b/src/basic_chain/js/test/pow.js similarity index 100% rename from src/js/test/pow.js rename to src/basic_chain/js/test/pow.js diff --git a/src/js/test/sync.js b/src/basic_chain/js/test/sync.js similarity index 100% rename from src/js/test/sync.js rename to src/basic_chain/js/test/sync.js diff --git a/src/js/test/transaction.js b/src/basic_chain/js/test/transaction.js similarity index 100% rename from src/js/test/transaction.js rename to src/basic_chain/js/test/transaction.js diff --git a/src/js/transaction.js b/src/basic_chain/js/transaction.js similarity index 100% rename from src/js/transaction.js rename to src/basic_chain/js/transaction.js