[
  {
    "path": ".gitignore",
    "content": "build\nclient/lib/contracts\nnode_modules\n"
  },
  {
    "path": "README.md",
    "content": "<h1 align=\"center\">Truffle and Next.js</h1> <br>\n<p align=\"center\">\n  <img alt=\"comet\" src=\"https://user-images.githubusercontent.com/943555/33169670-574322ee-cffa-11e7-9150-7b720ee0ee24.png\" width=\"120\">\n</p>\n<p align=\"center\">Rapid Ethereum Dapp Development</p>\n\n<p align=\"center\">\n  <img alt=\"made for ethereum\" src=\"https://img.shields.io/badge/made_for-ethereum-771ea5.svg\">\n  <img alt=\"to the moon\" src=\"https://img.shields.io/badge/to_the-moon-fab127.svg\">\n  <img alt=\"MIT license\" src=\"https://img.shields.io/badge/license-MIT-blue.svg\">\n</p>\n\n---\n\n# A Minimal Smart Contract Development Boilerplate\n\n[Truffle](https://github.com/trufflesuite/truffle) is great for developing Solidity smart contracts, but building a React frontend for a smart contract is often a chore. [Next.js](https://github.com/zeit/next.js) is one of the easiest ways to build such a frontend and the integration between Truffle and Next.js is what this boilerplate is trying to demonstrate.\n\nThere are two major features:\n\n- A plain `truffle init` project is used as the base (along with a SimpleStorage example contract).\n\n- A Next.js project resides in the `client` directory with a symlink to the output folder of the contract ABI definitions. The Next.js app also provides a simple skeleton for connecting to and interacting with the smart contract on a network.\n\nFor more information on how the frontend works, go read the [README.md](https://github.com/adrianmcli/truffle-next/blob/master/client/README.md) located in the `client` directory.\n\n## Installation\n\n1. Install Truffle globally.\n    ```bash\n    npm install -g truffle\n    ```\n\n2. Download the box. This also takes care of installing the necessary dependencies.\n    ```bash\n    truffle unbox adrianmcli/truffle-next\n    ```\n\n3. Run the development console.\n    ```bash\n    truffle develop\n    ```\n\n4. Compile and migrate the smart contracts. Note inside the development console we don't preface commands with `truffle`.\n    ```bash\n    compile\n    migrate\n    ```\n\n5. Run the next.js server for the front-end. Smart contract changes must be manually recompiled and migrated.\n    ```bash\n    // Change directory to the front-end folder\n    cd client\n    // Serves the front-end on http://localhost:3000\n    npm run dev\n    ```\n\n6. Truffle can run tests written in Solidity or JavaScript against your smart contracts. Note the command varies slightly if you're in or outside of the development console.\n    ```bash\n    // If inside the development console.\n    test\n\n    // If outside the development console..\n    truffle test\n    ```\n\n## Running with MetaMask\n\nSince `truffle develop` exposes the blockchain onto port `9545`, you'll need to add a Custom RPC network of `http://localhost:9545` in your MetaMask to make it work.\n\n## Running with TestRPC\n\nWe highly recommend using `truffle develop` over `testrpc`, but if you want to use `testrpc`, there are a couple things you need to do:\n\n- Change Line 6 of `client/lib/getWeb3.js` to use `localhost:8545` instead of `localhost:9545` so we refer to `testrpc` instead of `truffle develop`.\n- Run your `testrpc` with the following command (because [reasons](https://github.com/trufflesuite/truffle/issues/660#issuecomment-343066784)):\n\n   ```\n   testrpc --gasLimit 6721975 --gasPrice 100000000000\n   ```\n"
  },
  {
    "path": "client/.gitignore",
    "content": "node_modules\n.next\n"
  },
  {
    "path": "client/README.md",
    "content": "# Next.js client\n\nThis is the frontend client for our dapp. It is built with Next.js and uses a render-prop pattern (via `lib/Web3Container.js`) so we can easily inject blockchain functionality (i.e. web3, accounts, and the contract instance) into each page.\n\n## Pages\n\nThere are three pages:\n\n- `index.js` — This is a barebones Next.js page. It links to other pages which are web3-enabled. In your dapp, this can be a landing page.\n- `accounts.js` — This is a page listing the accounts returned from Web3. This file demonstrates the basic use of the `Web3Container` component.\n- `dapp.js` — This is a barebones demonstration dapp that utilizes the `Web3Container` component, but also makes calls to the contract. More specifically, it stores a value and gets a value.\n\n## The `lib` folder\n\n### `contracts`\n\nA symlink to the `build/contracts` located in the Truffle project is placed here so that the Next.js app can refer to the build artifacts from the parent Truffle project.\n\n### `Web3Container.js`\n\nThis is a component that utilizes the render-prop pattern to inject `web3`, `accounts`, and `contract` instance objects into a given function. When these objects are loading, it will render a loading function that is expected to return a React component.\n\nFor an example of how to use it, please see the `accounts` and `dapp` pages.\n\nYou may want to modify this for your own purposes. For example, you can require multiple contracts if your dapp requires it.\n\n### `getWeb3.js`\n\nThis is a function for actually getting the Web3 object. Unfortunately, this file is not as straight-forward as I would have liked it. Your best bet at understanding this is to read the comments I have written in the file. You probably don't need to change anything in this file.\n\n### `getContract.js`\n\nThis function requires `web3` to be passed in. It uses `truffle-contract` to initialize and return a contract instance. This function is used by `Web3Container.js`. You probably don't need to change anything in this file.\n\n### `getAccounts.js`\n\nThis simply wraps `web3.eth.getAccounts` into a Promise so we can use it cleanly inside `Web3Container.js`. You probably don't need to change anything in this file.\n"
  },
  {
    "path": "client/lib/Web3Container.js",
    "content": "import React from 'react'\nimport getWeb3 from './getWeb3'\nimport getContract from './getContract'\nimport contractDefinition from './contracts/SimpleStorage.json'\n\nexport default class Web3Container extends React.Component {\n  state = { web3: null, accounts: null, contract: null };\n\n  async componentDidMount () {\n    try {\n      const web3 = await getWeb3()\n      const accounts = await web3.eth.getAccounts()\n      const contract = await getContract(web3, contractDefinition)\n      this.setState({ web3, accounts, contract })\n    } catch (error) {\n      alert(\n        `Failed to load web3, accounts, or contract. Check console for details.`\n      )\n      console.log(error)\n    }\n  }\n\n  render () {\n    const { web3, accounts, contract } = this.state\n    return web3 && accounts\n      ? this.props.render({ web3, accounts, contract })\n      : this.props.renderLoading()\n  }\n}\n"
  },
  {
    "path": "client/lib/getContract.js",
    "content": "const getContractInstance = async (web3, contractDefinition) => {\n  // get network ID and the deployed address\n  const networkId = await web3.eth.net.getId()\n  const deployedAddress = contractDefinition.networks[networkId].address\n\n  // create the instance\n  const instance = new web3.eth.Contract(\n    contractDefinition.abi,\n    deployedAddress\n  )\n  return instance\n}\n\nexport default getContractInstance\n"
  },
  {
    "path": "client/lib/getWeb3.js",
    "content": "import Web3 from 'web3'\n\nconst resolveWeb3 = (resolve) => {\n  let { web3 } = window\n  const alreadyInjected = typeof web3 !== 'undefined' // i.e. Mist/Metamask\n  const localProvider = `http://localhost:9545`\n\n  if (alreadyInjected) {\n    console.log(`Injected web3 detected.`)\n    web3 = new Web3(web3.currentProvider)\n  } else {\n    console.log(`No web3 instance injected, using Local web3.`)\n    const provider = new Web3.providers.HttpProvider(localProvider)\n    web3 = new Web3(provider)\n  }\n\n  resolve(web3)\n}\n\nexport default () =>\n  new Promise((resolve) => {\n    // Wait for loading completion to avoid race conditions with web3 injection timing.\n    window.addEventListener(`load`, () => {\n      resolveWeb3(resolve)\n    })\n    // If document has loaded already, try to get Web3 immediately.\n    if (document.readyState === `complete`) {\n      resolveWeb3(resolve)\n    }\n  })\n"
  },
  {
    "path": "client/next.config.js",
    "content": "module.exports = {\n  webpack: (config, { buildId, dev }) => {\n    // This allows the app to refer to files through our symlink\n    config.resolve.symlinks = false\n    return config\n  }\n}\n"
  },
  {
    "path": "client/package.json",
    "content": "{\n  \"name\": \"client\",\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"dev\": \"next\",\n    \"build\": \"next build\",\n    \"start\": \"next start\",\n    \"link-contracts\": \"cd lib && ln -s ../../build/contracts contracts\"\n  },\n  \"dependencies\": {\n    \"next\": \"^6.1.1\",\n    \"react\": \"^16.4.1\",\n    \"react-dom\": \"^16.4.1\",\n    \"web3\": \"^1.0.0-beta.34\"\n  }\n}\n"
  },
  {
    "path": "client/pages/accounts.js",
    "content": "import React from 'react'\nimport Link from 'next/link'\nimport Web3Container from '../lib/Web3Container'\n\nconst Accounts = ({ accounts }) => (\n  <div>\n    <h1>My Accounts</h1>\n    <pre>{JSON.stringify(accounts, null, 4)}</pre>\n    <div><Link href='/dapp'><a>My Dapp</a></Link></div>\n    <div><Link href='/'><a>Home</a></Link></div>\n  </div>\n)\n\nexport default () => (\n  <Web3Container\n    renderLoading={() => <div>Loading Accounts Page...</div>}\n    render={({ accounts }) => <Accounts accounts={accounts} />}\n  />\n)\n"
  },
  {
    "path": "client/pages/dapp.js",
    "content": "import React from 'react'\nimport Link from 'next/link'\nimport Web3Container from '../lib/Web3Container'\n\nclass Dapp extends React.Component {\n  state = {\n    balance: undefined,\n    ethBalance: undefined\n  };\n\n  storeValue = async () => {\n    const { accounts, contract } = this.props\n    await contract.methods.set(5).send({ from: accounts[0] })\n    alert('Stored 5 into account')\n  };\n\n  getValue = async () => {\n    const { accounts, contract } = this.props\n    const response = await contract.methods.get().call({ from: accounts[0] })\n    this.setState({ balance: response })\n  };\n\n  getEthBalance = async () => {\n    const { web3, accounts } = this.props\n    const balanceInWei = await web3.eth.getBalance(accounts[0])\n    this.setState({ ethBalance: balanceInWei / 1e18 })\n  };\n\n  render () {\n    const { balance = 'N/A', ethBalance = 'N/A' } = this.state\n    return (\n      <div>\n        <h1>My Dapp</h1>\n\n        <button onClick={this.storeValue}>Store 5 into account balance</button>\n        <button onClick={this.getValue}>Get account balance</button>\n        <button onClick={this.getEthBalance}>Get ether balance</button>\n        <div>Account Balance: {balance}</div>\n        <div>Ether Balance: {ethBalance}</div>\n        <div>\n          <Link href='/accounts'>\n            <a>My Accounts</a>\n          </Link>\n        </div>\n        <div>\n          <Link href='/'>\n            <a>Home</a>\n          </Link>\n        </div>\n      </div>\n    )\n  }\n}\n\nexport default () => (\n  <Web3Container\n    renderLoading={() => <div>Loading Dapp Page...</div>}\n    render={({ web3, accounts, contract }) => (\n      <Dapp accounts={accounts} contract={contract} web3={web3} />\n    )}\n  />\n)\n"
  },
  {
    "path": "client/pages/index.js",
    "content": "import React from 'react'\nimport Link from 'next/link'\n\nexport default () =>\n  <div>\n    <h1>Home</h1>\n    <p>Note that Web3 is not loaded for this page.</p>\n    <div><Link href='/dapp'><a>My Dapp</a></Link></div>\n    <div><Link href='/accounts'><a>My Accounts</a></Link></div>\n  </div>\n"
  },
  {
    "path": "contracts/Migrations.sol",
    "content": "pragma solidity ^0.4.24;\n\ncontract Migrations {\n  address public owner;\n  uint public last_completed_migration;\n\n  modifier restricted() {\n    if (msg.sender == owner) _;\n  }\n\n  constructor() public {\n    owner = msg.sender;\n  }\n\n  function setCompleted(uint completed) public restricted {\n    last_completed_migration = completed;\n  }\n\n  function upgrade(address new_address) public restricted {\n    Migrations upgraded = Migrations(new_address);\n    upgraded.setCompleted(last_completed_migration);\n  }\n}\n"
  },
  {
    "path": "contracts/SimpleStorage.sol",
    "content": "\npragma solidity ^0.4.24;\n\ncontract SimpleStorage {\n  uint storedData;\n\n  function set(uint x) public {\n    storedData = x;\n  }\n\n  function get() public view returns (uint) {\n    return storedData;\n  }\n}\n"
  },
  {
    "path": "migrations/1_initial_migration.js",
    "content": "const Migrations = artifacts.require('./Migrations.sol')\n\nmodule.exports = function (deployer) {\n  deployer.deploy(Migrations)\n}\n"
  },
  {
    "path": "migrations/2_deploy_contracts.js",
    "content": "const SimpleStorage = artifacts.require('./SimpleStorage.sol')\n\nmodule.exports = function (deployer) {\n  deployer.deploy(SimpleStorage)\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"truffle-next\",\n  \"version\": \"1.0.0\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"lint\": \"standard\"\n  },\n  \"standard\": {\n    \"parser\": \"babel-eslint\",\n    \"envs\": [\n      \"mocha\",\n      \"browser\"\n    ],\n    \"globals\": [\n      \"artifacts\",\n      \"contract\",\n      \"assert\"\n    ]\n  },\n  \"devDependencies\": {\n    \"babel-eslint\": \"^8.0.2\",\n    \"standard\": \"^10.0.3\"\n  }\n}\n"
  },
  {
    "path": "test/TestSimpleStorage.sol",
    "content": "pragma solidity ^0.4.18;\n\nimport \"truffle/Assert.sol\";\nimport \"truffle/DeployedAddresses.sol\";\nimport \"../contracts/SimpleStorage.sol\";\n\ncontract TestSimpleStorage {\n\n  function testItStoresAValue() public {\n    SimpleStorage simpleStorage = SimpleStorage(DeployedAddresses.SimpleStorage());\n\n    simpleStorage.set(89);\n\n    uint expected = 89;\n\n    Assert.equal(simpleStorage.get(), expected, \"It should store the value 89.\");\n  }\n\n}\n"
  },
  {
    "path": "test/simplestorage.js",
    "content": "const SimpleStorage = artifacts.require('./SimpleStorage.sol')\n\ncontract('SimpleStorage', (accounts) => {\n  it('...should store the value 89.', async () => {\n    const simpleStorageInstance = await SimpleStorage.deployed()\n\n    // Set value of 89\n    await simpleStorageInstance.set(89, {from: accounts[0]})\n\n    // Get stored value\n    const storedData = await simpleStorageInstance.get.call()\n\n    assert.equal(storedData, 89, 'The value 89 was not stored.')\n  })\n})\n"
  },
  {
    "path": "truffle-box.json",
    "content": "{\n  \"ignore\": [\n    \"README.md\",\n    \".gitignore\",\n    \"package.json\",\n    \"box-img-lg.png\",\n    \"box-img-sm.png\",\n    \"package-lock.json\"\n  ],\n  \"commands\": {\n    \"Compile contracts\": \"truffle compile\",\n    \"Migrate contracts\": \"truffle migrate\",\n    \"Test contracts\": \"truffle test\"\n  },\n  \"hooks\": {\n    \"post-unpack\": \"cd client && npm install && npm run link-contracts\"\n  }\n}\n"
  },
  {
    "path": "truffle.js",
    "content": "module.exports = {\n  networks: {\n    development: {\n      host: 'localhost',\n      port: 8545,\n      network_id: '*' // Match any network id\n    }\n  },\n  solc: {\n    // Turns on the Solidity optimizer. For development the optimizer's\n    // quite helpful, just remember to be careful, and potentially turn it\n    // off, for live deployment and/or audit time. For more information,\n    // see the Truffle 4.0.0 release notes.\n    //\n    // https://github.com/trufflesuite/truffle/releases/tag/v4.0.0\n    optimizer: {\n      enabled: true,\n      runs: 200\n    }\n  }\n}\n"
  }
]