{"id":41824454,"url":"https://github.com/droxey/shoutouts.eth","last_synced_at":"2026-01-25T08:06:38.440Z","repository":{"id":38999094,"uuid":"380887622","full_name":"droxey/shoutouts.eth","owner":"droxey","description":null,"archived":false,"fork":false,"pushed_at":"2024-04-10T10:13:56.000Z","size":2826,"stargazers_count":1,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-04-14T10:07:37.746Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/droxey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2021-06-28T02:50:34.000Z","updated_at":"2024-04-14T10:07:37.747Z","dependencies_parsed_at":"2023-02-13T18:16:39.447Z","dependency_job_id":null,"html_url":"https://github.com/droxey/shoutouts.eth","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/droxey/shoutouts.eth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/droxey%2Fshoutouts.eth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/droxey%2Fshoutouts.eth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/droxey%2Fshoutouts.eth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/droxey%2Fshoutouts.eth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/droxey","download_url":"https://codeload.github.com/droxey/shoutouts.eth/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/droxey%2Fshoutouts.eth/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28748573,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T07:58:02.558Z","status":"ssl_error","status_checked_at":"2026-01-25T07:57:57.153Z","response_time":113,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-25T08:06:38.258Z","updated_at":"2026-01-25T08:06:38.424Z","avatar_url":"https://github.com/droxey.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# shoutouts.eth\n\n\n\u003cp align=\"center\"\u003e\n   \u003cimg src=\"shoutout.png\" alt=\"shoutout\"\u003e\n\u003c/p\u003e\n\n\u003c!-- omit in toc --\u003e\n## Table of Contents\n\n1. [**Backend**](#%2a%2abackend%2a%2a)\n   1. [Set Up Development Environment](#set-up-development-environment)\n   1. [Create Base Project](#create-base-project)\n   1. [Create Infura Account](#create-infura-account)\n   1. [Create Pinata Account](#create-pinata-account)\n   1. [Copy Mnemonic from MetaMask](#copy-mnemonic-from-metamask)\n   1. [Install Project Dependencies](#install-project-dependencies)\n   1. [Create Contract and Migration](#create-contract-and-migration)\n   1. [Create NFT Image](#create-nft-image)\n   1. [Create Sample Metadata File](#create-sample-metadata-file)\n   1. [Compile Contract](#compile-contract)\n   1. [Migrate to Rinkeby Network](#migrate-to-rinkeby-network)\n   1. [Test Deployed Contract in Console](#test-deployed-contract-in-console)\n   1. [Verify the Shoutout on the Blockchain](#verify-the-shoutout-on-the-blockchain)\n   1. [Add New Token to MetaMask](#add-new-token-to-metamask)\n1. [**Frontend**](#%2a%2afrontend%2a%2a)\n   1. [Prerequisites](#prerequisites)\n   1. [Setup Front End Codebase](#setup-front-end-codebase)\n   1. [Implement Front End Javascript](#implement-front-end-javascript)\n   1. [Build + Run Frontend](#build-%2B-run-frontend)\n   1. [Build for Production](#build-for-production)\n   1. [Open in MetaMask Enabled Browser](#open-in-metamask-enabled-browser)\n1. [Deploy](#deploy)\n   1. [Using Fleek + IPFS](#using-fleek-%2B-ipfs)\n1. [**Resources \u0026 Credits**](#%2a%2aresources-%26-credits%2a%2a)\n   1. [Books](#books)\n   1. [Guides](#guides)\n   1. [Repositories](#repositories)\n\n## **Backend**\n\n### Set Up Development Environment\n\n1. Install Truffle: `npm install -g truffle`\n1. Install Ganache: `npm install -g ganache-cli`\n1. Install Fleek: `npm install -g @fleekhq/fleek-cli`\n1. Download and install the IPFS CLI by following [these instructions](https://docs.ipfs.io/install/command-line/#official-distributions).\n1. Install the [Blockchain Development Kit for Ethereum](https://marketplace.visualstudio.com/items?itemName=AzBlockchain.azure-blockchain) extension in VSCode.\n\n\n### Create Base Project\n\n```bash\nmkdir shoutouts.eth\ncd shoutouts.eth\ntruffle init\nnpm init\ncp .env.sample .env\n```\n\n### Create Infura Account\n\n1. \u003cinfura.io\u003e: Sign up and create a new project. Give it the same name as your codebase.\n1. Under the Keys heading, copy `Project ID` to your clipboard.\n1. Open your `.env` file and paste the key to the right of `INFURA_KEY=`.\n\n### Create Pinata Account\n\n1. Visit \u003cpinata.cloud\u003e and create a new account.\n1. Click API Keys on left sidebar.\n1. Click `New Key`\n1. Turn on `Admin` level access.\n1. The name of the key should match the project name.\n1. Click `Create Key`. A modal dialog will appear. Click `Copy All` and store the values somewhere safe, like in a password manager.\n1. Copy `JWT` to the clipboard.\n\n\n### Copy Mnemonic from MetaMask\n\n1. Open Chrome and log in to MetaMask.\n1. Click Account Icon on Top Right \u003e Choose `Settings` \u003e `Security \u0026 Privacy`\n1. Click `Reveal Secret Recovery Phrase` and enter your MetaMask password.\n1. Copy the phrase to your clipboard.\n1. Open your `.env` file and paste the mnemonic to the right of `MNEMONIC=`.\n\n### Install Project Dependencies\n\n```bash\nnpm install @openzeppelin/contracts dotenv @truffle/hdwallet-provider@1.2.3\n```\n\n### Create Contract and Migration\n\n```bash\ntouch contracts/ShoutoutContract.sol\ntouch migrations/2_deploy_contracts.js\n```\n\n### Create NFT Image\n\n1. Visit https://badge.design to generate an image for your new token.\n1. Save a transparent PNG of the image in the root of your project.\n1. Open the IPFS Desktop application.\n1. Add the image to IPFS:\n\n   ```bash\n   $ ipfs init\n   generating ED25519 keypair...done\n   peer identity: 12D3KooWK9J7NfuE9wGKWpERRLWDhcpUwhfduu4osbhV2TamQeRZ\n   initializing IPFS node at /Users/droxey/.ipfs\n\n\n   $ ipfs daemon\n   Initializing daemon...\n   go-ipfs version: 0.9.0\n   Repo version: 11\n   System version: arm64/darwin\n   Golang version: go1.16.5\n   Swarm listening on /ip4/127.0.0.1/tcp/4001\n   Swarm listening on /ip4/127.0.0.1/udp/4001/quic\n   Swarm listening on /ip4/192.168.0.118/tcp/4001\n   Swarm listening on /ip4/192.168.0.118/udp/4001/quic\n   Swarm listening on /ip4/192.168.0.173/tcp/4001\n   Swarm listening on /ip4/192.168.0.173/udp/4001/quic\n   Swarm listening on /ip6/::1/tcp/4001\n   Swarm listening on /ip6/::1/udp/4001/quic\n   Swarm listening on /ip6/fdc4:67f5:8ffa:3:144b:dbb3:b143:89a0/tcp/4001\n   Swarm listening on /ip6/fdc4:67f5:8ffa:3:144b:dbb3:b143:89a0/udp/4001/quic\n   Swarm listening on /ip6/fdc4:67f5:8ffa:3:cf5:b55b:8447:a756/tcp/4001\n   Swarm listening on /ip6/fdc4:67f5:8ffa:3:cf5:b55b:8447:a756/udp/4001/quic\n   Swarm listening on /p2p-circuit\n   Swarm announcing /ip4/127.0.0.1/tcp/4001\n   Swarm announcing /ip4/127.0.0.1/udp/4001/quic\n   Swarm announcing /ip4/192.168.0.173/tcp/4001\n   Swarm announcing /ip4/192.168.0.173/udp/4001/quic\n   Swarm announcing /ip4/71.204.188.97/udp/4001/quic\n   Swarm announcing /ip6/::1/tcp/4001\n   Swarm announcing /ip6/::1/udp/4001/quic\n   API server listening on /ip4/127.0.0.1/tcp/5001\n   WebUI: http://127.0.0.1:5001/webui\n   Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8080\n   Daemon is ready\n   ```\n\n1. In a new terminal tab, run `ipfs add shoutout.png` to add the token's image to IPFS:\n\n   ```bash\n   $ ipfs add shoutout.png\n   added QmRGhvqTPvx8kgMSLFdPaCysKvhtP5GV5MsKDmTx3v2QxT shoutout.png\n   10.79 KiB / 10.79 KiB [=======================================================================================================================================================] 100.00%\n   ```\n\n   Copy the hash you receive when adding the image. This is the address of your image in IPFS.\n\n1. Pin the image in Pinata:\n\n   ```bash\n   $ ipfs pin remote service add pinata https://api.pinata.cloud/psa PASTE_JWT_KEY\n   $ ipfs pin remote add --service=pinata --name=shoutout.png QmRGhvqTPvx8kgMSLFdPaCysKvhtP5GV5MsKDmTx3v2QxT\n   ```\n\n### Create Sample Metadata File\n\nThis sample metadata can be used prior to developing a metadata API, and exists to prove that we can mint our token successfully.\n\n1. Add the file to IPFS:\n\n   ```bash\n   $ ipfs add sample-metadata.json\n   added QmVGmwHFxzcrdygWMKPdqp3Q37BBNsGc4M1f6KVRitJ49j sample-metadata.json\n   196 B / 196 B [===============================================================================================================================================================] 100.00%\n   ```\n\n1. Pin the file in Pinata:\n\n   ```bash\n   $ ipfs pin remote add --service=pinata --name=sample-metadata.json QmVGmwHFxzcrdygWMKPdqp3Q37BBNsGc4M1f6KVRitJ49j\n   CID:    QmVGmwHFxzcrdygWMKPdqp3Q37BBNsGc4M1f6KVRitJ49j\n   Name:   sample-metadata.json\n   Status: pinned\n   ```\n\n### Compile Contract\n\n```bash\n$ truffle compile\n\nCompiling your contracts...\n===========================\n\n\u003e Compiling ./contracts/Migrations.sol\n\u003e Compiling ./contracts/ShoutoutContract.sol\n\u003e Compiling @openzeppelin/contracts/token/ERC721/ERC721.sol\n\u003e Compiling @openzeppelin/contracts/token/ERC721/IERC721.sol\n\u003e Compiling @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\n\u003e Compiling @openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol\n\u003e Compiling @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol\n\u003e Compiling @openzeppelin/contracts/utils/Address.sol\n\u003e Compiling @openzeppelin/contracts/utils/Context.sol\n\u003e Compiling @openzeppelin/contracts/utils/Counters.sol\n\u003e Compiling @openzeppelin/contracts/utils/Strings.sol\n\u003e Compiling @openzeppelin/contracts/utils/introspection/ERC165.sol\n\u003e Compiling @openzeppelin/contracts/utils/introspection/IERC165.sol\n\n\u003e Artifacts written to /Users/droxey/dev/repos/shoutouts.eth/build/contracts\n\u003e Compiled successfully using:\n   - solc: 0.8.0+commit.c7dfd78e.Linux.g++\n```\n\n### Migrate to Rinkeby Network\n\n```bash\n$ truffle migrate --network rinkeby\n\nCompiling your contracts...\n===========================\n\u003e Everything is up to date, there is nothing to compile.\n\n\n\nStarting migrations...\n======================\n\u003e Network name:    'rinkeby'\n\u003e Network id:      4\n\u003e Block gas limit: 10000000 (0x989680)\n\n\n1_initial_migration.js\n======================\n\n   Deploying 'Migrations'\n   ----------------------\n   \u003e transaction hash:    0x3d7e525301cb45c617ddfc1977397e9f5ee74b1f4679851ada897994bf08e9e4\n   \u003e Blocks: 1            Seconds: 12\n   \u003e contract address:    0xAf47d95c283b8d0333ADEDAF0bB22916ceFFA7FB\n   \u003e block number:        8841341\n   \u003e block timestamp:     1624856784\n   \u003e account:             0xe4233b38fEa3B8c27ea9F54d5A90ec27cEe7F42C\n   \u003e balance:             1.556150107\n   \u003e gas used:            251534 (0x3d68e)\n   \u003e gas price:           1 gwei\n   \u003e value sent:          0 ETH\n   \u003e total cost:          0.000251534 ETH\n\n   Pausing for 2 confirmations...\n   ------------------------------\n   \u003e confirmation number: 1 (block: 8841342)\n   \u003e confirmation number: 2 (block: 8841343)\n\n   \u003e Saving migration to chain.\n   \u003e Saving artifacts\n   -------------------------------------\n   \u003e Total cost:         0.000251534 ETH\n\n\n2_deploy_contracts.js\n=====================\n\n   Deploying 'ShoutoutContract'\n   ----------------------------\n   \u003e transaction hash:    0xea92115a2eb4d8d6164bcbb52714e7c42fccb9de09a060457b128fcf1877ffc6\n   \u003e Blocks: 1            Seconds: 12\n   \u003e contract address:    0x001Fd4dd63455F327BE312C6bf7c77c5A63BEe9e\n   \u003e block number:        8841345\n   \u003e block timestamp:     1624856844\n   \u003e account:             0xe4233b38fEa3B8c27ea9F54d5A90ec27cEe7F42C\n   \u003e balance:             1.553639137\n   \u003e gas used:            2465052 (0x259d1c)\n   \u003e gas price:           1 gwei\n   \u003e value sent:          0 ETH\n   \u003e total cost:          0.002465052 ETH\n\n   Pausing for 2 confirmations...\n   ------------------------------\n   \u003e confirmation number: 1 (block: 8841346)\n   \u003e confirmation number: 2 (block: 8841347)\n\n   \u003e Saving migration to chain.\n   \u003e Saving artifacts\n   -------------------------------------\n   \u003e Total cost:         0.002465052 ETH\n\n\nSummary\n=======\n\u003e Total deployments:   2\n\u003e Final cost:          0.002716586 ETH\n```\n\n### Test Deployed Contract in Console\n\n```bash\n$ truffle console --network rinkeby\ntruffle(rinkeby)\u003e let instance = await ShoutoutContract.deployed()\ntruffle(rinkeby)\u003e let result = await instance.awardItem(\"0xe4233b38fEa3B8c27ea9F54d5A90ec27cEe7F42C\", \"https://gateway.pinata.cloud/ipfs/QmVGmwHFxzcrdygWMKPdqp3Q37BBNsGc4M1f6KVRitJ49j\")\n```\n\n### Verify the Shoutout on the Blockchain\n\n1. Open https://rinkeby.etherscan.io\n1. Paste the deployed contract address in the search bar or visit \u003chttps://rinkeby.etherscan.io/address/DEPLOYED_CONTRACT_ADDRESS\u003e  (https://rinkeby.etherscan.io/address/0x001Fd4dd63455F327BE312C6bf7c77c5A63BEe9e)\n1. Should see two transactions --- one to create the contract, and one to award an item.\n\n### Add New Token to MetaMask\n\n1. Open MetaMask and click Add Token\n1. Paste the deployed contract address in the `Token Contract Address` field.\n1. Set Token Decimal to 0.\n1. Click `Next`\n1. Click `Add Token`\n\n## **Frontend**\n\n### Prerequisites\n\n1. Sign up for an account on fleek.co (one per team)\n2. Add team members by going to the Members link on the sidebar.\n3. Go to the Storage tab on the sidebar and click Create Folder. \n4. Name the folder `metadata`.\n5. Generate a Storage API Key by clicking your name at the bottom of the page, then choosing Settings. Scroll to the bottom to generate a new API key. \n6. Use these keys in your JS to upload files on Fleek!\n\n### Setup Front End Codebase\n\n1. Add `app` folder to project. Name is important!\n1. Add  `app/js/index.js` to the project.\n1. Add `app/index.html` to the project.\n\n### Implement Front End Javascript\n\nLocated in `app/js/index.js`.\n\n### Add Webpack\n\n1. Open your `package.json` file and paste the `script` object found below ([example](https://github.com/droxey/shoutouts.eth/blob/master/package.json#L9):\n\n   ```json\n   \"scripts\": {\n     \"lint\": \"eslint ./\",\n     \"build\": \"webpack\",\n     \"dev\": \"webpack-dev-server\"\n   },\n   ```\n   \n1. At the bottom of `package.json`, paste the following `devDependencies` for webpack ([example](https://github.com/droxey/shoutouts.eth/blob/master/package.json#L33):\n\n   ```json\n     \"devDependencies\": {\n       \"copy-webpack-plugin\": \"^5.0.5\",\n       \"webpack\": \"^4.41.2\",\n       \"webpack-cli\": \"^3.3.10\",\n       \"webpack-dev-server\": \"^3.9.0\"\n   }\n   ```\n   \n1. Run `npm install` to install the new `devDependencies`.\n1. Copy `webpack.config.js` from this repo and customize it based on your needs.\n\n### Build + Run Frontend\n\nIn the `app` directory, we build and run our frontend.\n\nSmart contract changes must be manually recompiled and migrated.\n\nOpen another terminal and run the following commands to build the frontend:\n\n```bash\ncd app\nnpm run dev\n```\n\n### Build for Production\n\nOpen a fresh terminal and run the following commands to build the frontend:\n\n```bash\ncd app\nnpm run build\n```\n\nThe production build will be in the `dist` folder after running `npm run build`  in the `app` folder.\n\nThis build can be deployed anywhere static sites can be hosted!\n\n### Open in MetaMask Enabled Browser\n\nVisit \u003chttp://localhost:8080\u003e in your browser to test your new full stack DApp!\n\n\n## Deploy\n\n### Using Fleek + IPFS\n\n1. Visit \u003cfleek.co\u003e in your browser and create an account.\n1. Run `fleek login` to sign in from your terminal before initializing or deploying.\n1. Initialize fleek for your project:\n\n   ```bash\n   $ fleek site:init\n   'This command will walk you through initializing a new or existing fleek site config in the current directory.'\n\n   'Successfully initializing a site would create a .fleek.json file in your directory.'\n   'You can then use `fleek site:deploy` to deploy changes made to your publish directory.'\n\n   ? Which team you wanna use? username-team\n   ...fetching list of sites for team: username-team\n   ? Which site you wanna use? Create new site\n   ? Select the public directory for deployment ('.' for current directory): .\n   publishing files in /Users/droxey/dev/repos/shoutouts.eth to IPFS\n   packaging site contents...\n   uploading...\n   Site cid is QmULzpjfa3CbBRktd2744jXYqWbYjkHTYd9sbvthzkTkzx\n   creating new site\n   Fleek site late-dust-7939 was successfully initialized.\n   ```\n\n1. Deploy the entire project to IPFS:\n\n   ```bash\n   $ fleek site:deploy\n   publishing files in /Users/droxey/dev/repos/shoutouts.eth to IPFS\n   packaging site contents...\n   uploading...\n   Site cid is QmTRnEN27nJLpXFiXEZ8NTr4wE4q5ssg9F9hqztnHrjYso\n   New deployment has been triggered.\n   View deployment here: https://app.fleek.co/#/sites/late-dust-7939/deploys/2021-06-28T04:34:52.361Z?accountId=username-team\n   ```\n\n## **Resources \u0026 Credits**\n\n### Books\n\n- [**Building Blockchain Projects** by Narayan Prusty](https://learning.oreilly.com/library/view/building-blockchain-projects)\n- [**Get Started With Ethereum** by Davi Bauer](https://leanpub.com/getstartedwithethereum)\n\n### Guides\n\n- [webpack | Boxes | Truffle Suite](https://www.trufflesuite.com/boxes/webpack)\n- [Easily pin to IPFS with Fleek Storage Js! - A short guide - Fleek Blog](https://blog.fleek.co/posts/guide-to-fleek-storage-js)\n\n### Repositories\n\n- [truffle-box/webpack-box: Example webpack-based app for Truffle (boilerplate)](https://github.com/truffle-box/webpack-box)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdroxey%2Fshoutouts.eth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdroxey%2Fshoutouts.eth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdroxey%2Fshoutouts.eth/lists"}