├── client
├── src
│ ├── vite-env.d.ts
│ ├── utils
│ │ ├── shortenAddress.ts
│ │ ├── constants.ts
│ │ ├── dummyData.ts
│ │ └── Transactions.json
│ ├── components
│ │ ├── Loader
│ │ │ └── Loader.tsx
│ │ ├── index.tsx
│ │ ├── Footer
│ │ │ └── Footer.tsx
│ │ ├── Services
│ │ │ └── Services.tsx
│ │ ├── Navbar
│ │ │ └── Navbar.tsx
│ │ ├── Transactions
│ │ │ └── Transactions.tsx
│ │ └── Welcome
│ │ │ └── Welcome.tsx
│ ├── main.tsx
│ ├── App.tsx
│ ├── App.css
│ ├── hooks
│ │ └── useFetch.tsx
│ ├── favicon.svg
│ ├── logo.svg
│ ├── index.css
│ └── context
│ │ └── TransactionContext.tsx
├── images
│ ├── logo.png
│ ├── hello.svg
│ └── animated.svg
├── .gitignore
├── postcss.config.js
├── vite.config.ts
├── index.html
├── tsconfig.json
├── package.json
└── tailwind.config.js
└── smart_contract
├── .gitignore
├── hardhat.config.js
├── README.md
├── package.json
├── scripts
└── deploy.js
├── test
└── sample-test.js
└── contracts
└── Transactions.sol
/client/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/client/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fantasy1114/web3_crypto/HEAD/client/images/logo.png
--------------------------------------------------------------------------------
/client/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | dist
4 | dist-ssr
5 | *.local
6 | .env
7 | .env.local
8 |
9 | .vercel
10 |
--------------------------------------------------------------------------------
/client/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/smart_contract/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .env
3 | coverage
4 | coverage.json
5 | typechain
6 |
7 | #Hardhat files
8 | cache
9 | artifacts
10 |
--------------------------------------------------------------------------------
/client/src/utils/shortenAddress.ts:
--------------------------------------------------------------------------------
1 | export const shortenAddress = (address: string) => {
2 | return `${address.slice(0, 6)}...${address.slice(address.length - 4)}`;
3 | };
4 |
--------------------------------------------------------------------------------
/client/src/utils/constants.ts:
--------------------------------------------------------------------------------
1 | import abi from './Transactions.json';
2 |
3 | export const contractAddress = '0xbA1252D38fAC5AFa1fe74b7661c1a062C4D1a0D3';
4 |
5 | export const contractABI = abi.abi;
6 |
--------------------------------------------------------------------------------
/client/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()]
7 | })
8 |
--------------------------------------------------------------------------------
/client/src/components/Loader/Loader.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Loader = () => {
4 | return (
5 |
8 | );
9 | };
10 |
11 | export default Loader;
12 |
--------------------------------------------------------------------------------
/client/src/components/index.tsx:
--------------------------------------------------------------------------------
1 | import Footer from './Footer/Footer';
2 | import Navbar from './Navbar/Navbar';
3 | import Loader from './Loader/Loader';
4 | import Services from './Services/Services';
5 | import Transactions from './Transactions/Transactions';
6 | import Welcome from './Welcome/Welcome';
7 |
8 | export { Footer, Navbar, Loader, Services, Transactions, Welcome };
9 |
--------------------------------------------------------------------------------
/client/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import { TransactionsProvider } from './context/TransactionContext';
6 |
7 | ReactDOM.render(
8 |
9 |
10 |
11 |
12 | ,
13 | document.getElementById('root')
14 | );
15 |
--------------------------------------------------------------------------------
/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/smart_contract/hardhat.config.js:
--------------------------------------------------------------------------------
1 | // https://eth-ropsten.alchemyapi.io/v2/1Fu4Jn3DcjegvS56l2UINAshrHVdtPJz
2 |
3 | require('@nomiclabs/hardhat-waffle');
4 |
5 | module.exports = {
6 | solidity: '0.8.0',
7 | networks: {
8 | ropsten: {
9 | url: 'https://eth-ropsten.alchemyapi.io/v2/1Fu4Jn3DcjegvS56l2UINAshrHVdtPJz',
10 | accounts: ['c9c4b7e083ce851abaac82fb79be13b647460072bf671bc9358f316880e3e846'],
11 | },
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/client/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import { Navbar, Footer, Loader, Transactions, Services, Welcome } from './components';
3 |
4 | const App = () => {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | );
17 | };
18 |
19 | export default App;
20 |
--------------------------------------------------------------------------------
/smart_contract/README.md:
--------------------------------------------------------------------------------
1 | # Basic Sample Hardhat Project
2 |
3 | This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, a sample script that deploys that contract, and an example of a task implementation, which simply lists the available accounts.
4 |
5 | Try running some of the following tasks:
6 |
7 | ```shell
8 | npx hardhat accounts
9 | npx hardhat compile
10 | npx hardhat clean
11 | npx hardhat test
12 | npx hardhat node
13 | node scripts/sample-script.js
14 | npx hardhat help
15 | ```
16 |
--------------------------------------------------------------------------------
/smart_contract/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "smart_contract",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "devDependencies": {
10 | "@nomiclabs/hardhat-ethers": "^2.0.3",
11 | "@nomiclabs/hardhat-waffle": "^2.0.1",
12 | "chai": "^4.3.4",
13 | "ethereum-waffle": "^3.4.0",
14 | "ethers": "^5.5.2",
15 | "hardhat": "^2.8.0"
16 | },
17 | "keywords": [],
18 | "author": "",
19 | "license": "ISC"
20 | }
21 |
--------------------------------------------------------------------------------
/client/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx",
18 | "types": ["vite/client"]
19 | },
20 | "include": ["./src"]
21 | }
22 |
--------------------------------------------------------------------------------
/smart_contract/scripts/deploy.js:
--------------------------------------------------------------------------------
1 | const main = async () => {
2 | const Transactions = await hre.ethers.getContractFactory('Transactions');
3 | const transactions = await Transactions.deploy();
4 |
5 | await transactions.deployed();
6 |
7 | console.log('Transactions deployed to:', transactions.address);
8 | };
9 |
10 | // main()
11 | // .then(() => process.exit(0))
12 | // .catch((error) => {
13 | // console.error(error);
14 | // process.exit(1);
15 | // });
16 |
17 | const runMain = async () => {
18 | try {
19 | await main();
20 | process.exit(0);
21 | } catch (e) {
22 | console.error(e);
23 | process.exit(1);
24 | }
25 | };
26 |
27 | runMain();
28 |
--------------------------------------------------------------------------------
/smart_contract/test/sample-test.js:
--------------------------------------------------------------------------------
1 | const { expect } = require("chai");
2 | const { ethers } = require("hardhat");
3 |
4 | describe("Greeter", function () {
5 | it("Should return the new greeting once it's changed", async function () {
6 | const Greeter = await ethers.getContractFactory("Greeter");
7 | const greeter = await Greeter.deploy("Hello, world!");
8 | await greeter.deployed();
9 |
10 | expect(await greeter.greet()).to.equal("Hello, world!");
11 |
12 | const setGreetingTx = await greeter.setGreeting("Hola, mundo!");
13 |
14 | // wait until the transaction is mined
15 | await setGreetingTx.wait();
16 |
17 | expect(await greeter.greet()).to.equal("Hola, mundo!");
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "web3app",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "dev": "vite",
6 | "build": "tsc && vite build",
7 | "preview": "vite preview"
8 | },
9 | "dependencies": {
10 | "@tailwindcss/forms": "^0.4.0",
11 | "ethers": "^5.5.3",
12 | "react": "^17.0.2",
13 | "react-dom": "^17.0.2",
14 | "react-icons": "^4.3.1"
15 | },
16 | "devDependencies": {
17 | "@types/node": "^17.0.8",
18 | "@types/react": "^17.0.33",
19 | "@types/react-dom": "^17.0.10",
20 | "@vitejs/plugin-react": "^1.0.7",
21 | "autoprefixer": "^10.4.2",
22 | "postcss": "^8.4.5",
23 | "sass": "^1.48.0",
24 | "tailwindcss": "^3.0.13",
25 | "typescript": "^4.4.4",
26 | "vite": "^2.7.2"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/client/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
40 | button {
41 | font-size: calc(10px + 2vmin);
42 | }
43 |
--------------------------------------------------------------------------------
/client/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
3 | mode: 'jit',
4 | darkMode: false, // or 'media' or 'class'
5 | theme: {
6 | fontFamily: {
7 | display: ['Open Sans', 'sans-serif'],
8 | body: ['Open Sans', 'sans-serif'],
9 | },
10 | extend: {
11 | screens: {
12 | mf: '990px',
13 | },
14 | keyframes: {
15 | 'slide-in': {
16 | '0%': {
17 | '-webkit-transform': 'translateX(120%)',
18 | transform: 'translateX(120%)',
19 | },
20 | '100%': {
21 | '-webkit-transform': 'translateX(0%)',
22 | transform: 'translateX(0%)',
23 | },
24 | },
25 | },
26 | animation: {
27 | 'slide-in': 'slide-in 0.5s ease-out',
28 | },
29 | },
30 | },
31 | variants: {
32 | extend: {},
33 | },
34 | plugins: [require('@tailwindcss/forms')],
35 | };
36 |
--------------------------------------------------------------------------------
/client/src/hooks/useFetch.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 |
3 | const APIKEY = import.meta.env.VITE_GIPHY_API;
4 |
5 | interface useFetchProps {
6 | keyword: string;
7 | }
8 |
9 | const useFetch = ({ keyword }: useFetchProps) => {
10 | const [gifUrl, setGifUrl] = useState('');
11 |
12 | const fetchGifs = async () => {
13 | await fetch(
14 | `https://api.giphy.com/v1/gifs/search?api_key=${APIKEY}&q=${keyword
15 | .split(' ')
16 | .join('')}&limit=1`
17 | )
18 | .then((res) => res.json())
19 | .then(({ data }) => {
20 | setGifUrl(data?.[0]?.images?.downsized_medium?.url);
21 | if (!data.length) {
22 | setGifUrl('https://metro.co.uk/wp-content/uploads/2015/05/pokemon_crying.gif');
23 | }
24 | })
25 | .catch((err) => {
26 | console.log(err);
27 | setGifUrl('https://metro.co.uk/wp-content/uploads/2015/05/pokemon_crying.gif');
28 | });
29 | };
30 |
31 | useEffect(() => {
32 | if (keyword) {
33 | console.log('keyword: ', keyword.split(' ').join(''));
34 | fetchGifs();
35 | }
36 | }, [keyword]);
37 |
38 | return gifUrl;
39 | };
40 |
41 | export default useFetch;
42 |
--------------------------------------------------------------------------------
/client/src/favicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/client/src/components/Footer/Footer.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import logo from '../../../images/logo.png';
3 |
4 | const Footer = () => {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
Market
13 |
Exchange
14 |
Tutorials
15 |
Wallet
16 |
17 |
18 |
19 |
Come join us
20 |
info@crypto.com
21 |
22 |
23 |
24 |
25 |
26 |
@Cryptoapp 2022
27 |
All rights reserved
28 |
29 |
30 | );
31 | };
32 |
33 | export default Footer;
34 |
--------------------------------------------------------------------------------
/smart_contract/contracts/Transactions.sol:
--------------------------------------------------------------------------------
1 | //SPDX-License-Identifier: Unlicensed
2 | pragma solidity ^0.8.0;
3 |
4 | contract Transactions {
5 | uint256 transactionsCount;
6 |
7 | event Transfer(
8 | address from,
9 | address receiver,
10 | uint256 amount,
11 | string message,
12 | uint256 timestamp,
13 | string keyword
14 | );
15 |
16 | struct TransferStruct {
17 | address from;
18 | address receiver;
19 | uint256 amount;
20 | string message;
21 | uint256 timestamp;
22 | string keyword;
23 | }
24 |
25 | TransferStruct[] transactions;
26 |
27 | function addToBlockChain(
28 | address payable receiver,
29 | uint256 amount,
30 | string memory message,
31 | string memory keyword
32 | ) public {
33 | transactionsCount += 1;
34 | transactions.push(
35 | TransferStruct(
36 | msg.sender,
37 | receiver,
38 | amount,
39 | message,
40 | block.timestamp,
41 | keyword
42 | )
43 | );
44 |
45 | emit Transfer(
46 | msg.sender,
47 | receiver,
48 | amount,
49 | message,
50 | block.timestamp,
51 | keyword
52 | );
53 | }
54 |
55 | function getAllTransactions()
56 | public
57 | view
58 | returns (TransferStruct[] memory)
59 | {
60 | return transactions;
61 | }
62 |
63 | function getTransactionCount() public view returns (uint256) {
64 | return transactionsCount;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/client/src/utils/dummyData.ts:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | id: 1,
4 | url: 'https://metro.co.uk/wp-content/uploads/2015/05/pokemon_crying.gif?quality=90&strip=all&zoom=1&resize=500%2C284',
5 | message: '',
6 | timestamp: '12/21/2021, 4:33:21 PM',
7 | addressFrom: '0xCF8e569A97C423952DdFf902375C7C76549A6A90',
8 | amount: '0.01',
9 | addressTo: '0x8aa395Ab97837576aF9cd6946C79024ef1acfdbE',
10 | },
11 | {
12 | id: 2,
13 | url: 'https://media4.popsugar-assets.com/files/2013/11/07/832/n/1922398/eb7a69a76543358d_28.gif',
14 | message: '',
15 | timestamp: '12/21/2021, 4:33:21 PM',
16 | addressFrom: '0xCF8e569A97C423952DdFf902375C7C76549A6A90',
17 | amount: '0.01',
18 | addressTo: '0x8aa395Ab97837576aF9cd6946C79024ef1acfdbE',
19 | },
20 | {
21 | id: 3,
22 | url: 'https://acegif.com/wp-content/uploads/gif-shaking-head-38.gif',
23 | message: '',
24 | timestamp: '12/21/2021, 4:33:21 PM',
25 | addressFrom: '0xCF8e569A97C423952DdFf902375C7C76549A6A90',
26 | amount: '0.01',
27 | addressTo: '0x8aa395Ab97837576aF9cd6946C79024ef1acfdbE',
28 | },
29 | {
30 | id: 4,
31 | url: 'https://i.pinimg.com/originals/68/a0/9e/68a09e774e98242871c2db0f99307420.gif',
32 | message: '',
33 | timestamp: '12/21/2021, 4:33:21 PM',
34 | addressFrom: '0xCF8e569A97C423952DdFf902375C7C76549A6A90',
35 | amount: '0.01',
36 | addressTo: '0x8aa395Ab97837576aF9cd6946C79024ef1acfdbE',
37 | },
38 | {
39 | id: 5,
40 | url: 'https://i.pinimg.com/originals/73/d3/a1/73d3a14d212314ab1f7268b71d639c15.gif',
41 | message: '',
42 | timestamp: '12/21/2021, 4:33:21 PM',
43 | addressFrom: '0xCF8e569A97C423952DdFf902375C7C76549A6A90',
44 | amount: '0.01',
45 | addressTo: '0x8aa395Ab97837576aF9cd6946C79024ef1acfdbE',
46 | },
47 | {
48 | id: 6,
49 | url: 'https://www.omnisend.com/blog/wp-content/uploads/2016/09/funny-gifs-9.gif',
50 | message: '',
51 | timestamp: '12/21/2021, 4:33:21 PM',
52 | addressFrom: '0xCF8e569A97C423952DdFf902375C7C76549A6A90',
53 | amount: '0.01',
54 | addressTo: '0x8aa395Ab97837576aF9cd6946C79024ef1acfdbE',
55 | },
56 | ];
57 |
--------------------------------------------------------------------------------
/client/src/components/Services/Services.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { BsShieldFillCheck } from 'react-icons/bs';
3 | import { BiSearchAlt } from 'react-icons/bi';
4 | import { RiHeart2Fill } from 'react-icons/ri';
5 |
6 | interface ServiceCardProps {
7 | color: string;
8 | title: string;
9 | subtitle: string;
10 | icon: React.ReactNode;
11 | }
12 |
13 | const ServiceCard = ({ color, title, icon, subtitle }: ServiceCardProps) => {
14 | return (
15 |
16 |
17 | {icon}
18 |
19 |
20 |
{title}
21 |
{subtitle}
22 |
23 |
24 | );
25 | };
26 |
27 | const Services = () => {
28 | return (
29 |
30 |
31 |
32 |
33 | Services that we
34 | continue to improve
35 |
36 |
37 |
38 |
39 |
40 | }
44 | subtitle='Security is guranteed. We always maintain privacy and maintain the quality of our products'
45 | />
46 | }
50 | subtitle='Security is guranteed. We always maintain privacy and maintain the quality of our products'
51 | />
52 | }
56 | subtitle='Security is guranteed. We always maintain privacy and maintain the quality of our products'
57 | />
58 |
59 |
60 | );
61 | };
62 |
63 | export default Services;
64 |
--------------------------------------------------------------------------------
/client/src/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/client/src/components/Navbar/Navbar.tsx:
--------------------------------------------------------------------------------
1 | import React, { useContext, useState } from 'react';
2 | import { HiMenuAlt4 } from 'react-icons/hi';
3 | import { AiOutlineClose } from 'react-icons/ai';
4 | import Logo from '../../../images/logo.png';
5 | import { TransactionContext } from '../../context/TransactionContext';
6 |
7 | const NavbarItem = ({
8 | title,
9 | classProps = '',
10 | }: {
11 | title: string;
12 | classProps?: React.HTMLAttributes['className'];
13 | }) => {
14 | return {title} ;
15 | };
16 |
17 | const Navbar = () => {
18 | const [toggleMenu, setToggleMenu] = useState(false);
19 | const { currentAccount, connectWallet } = useContext(TransactionContext);
20 |
21 | return (
22 |
23 |
24 |
25 |
26 |
27 | {['Market', 'Exchange', 'Tutorials', 'Wallets'].map((title, index) => {
28 | return ;
29 | })}
30 |
33 | Login
34 |
35 |
36 |
37 | {toggleMenu ? (
38 |
setToggleMenu(false)}
41 | fontSize={28}
42 | />
43 | ) : (
44 | setToggleMenu(true)}
48 | />
49 | )}
50 |
51 | {toggleMenu && (
52 |
55 |
56 | setToggleMenu(false)}
59 | fontSize={28}
60 | />
61 |
62 | {['Market', 'Exchange', 'Tutorials', 'Wallets'].map((title, index) => {
63 | return ;
64 | })}
65 |
66 | )}
67 |
68 |
69 | );
70 | };
71 |
72 | export default Navbar;
73 |
--------------------------------------------------------------------------------
/client/src/index.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700&display=swap');
2 |
3 | @tailwind base;
4 | @tailwind components;
5 | @tailwind utilities;
6 |
7 | * html {
8 | padding: 0;
9 | margin: 0;
10 | box-sizing: border-box;
11 | }
12 |
13 | body {
14 | margin: 0;
15 | font-family: 'Open Sans', sans-serif;
16 | -webkit-font-smoothing: antialiased;
17 | -moz-osx-font-smoothing: grayscale;
18 | }
19 |
20 | .gradient-bg-welcome {
21 | background-color: #0f0e13;
22 | background-image: radial-gradient(at 0% 0%, hsla(253, 16%, 7%, 1) 0, transparent 50%),
23 | radial-gradient(at 50% 0%, hsla(225, 39%, 30%, 1) 0, transparent 50%),
24 | radial-gradient(at 100% 0%, hsla(339, 49%, 30%, 1) 0, transparent 50%);
25 | }
26 |
27 | .gradient-bg-services {
28 | background-color: #0f0e13;
29 | background-image: radial-gradient(at 0% 0%, hsla(253, 16%, 7%, 1) 0, transparent 50%),
30 | radial-gradient(at 50% 100%, hsla(225, 39%, 25%, 1) 0, transparent 50%);
31 | }
32 |
33 | .gradient-bg-transactions {
34 | background-color: #0f0e13;
35 | background-image: radial-gradient(at 0% 100%, hsla(253, 16%, 7%, 1) 0, transparent 50%),
36 | radial-gradient(at 50% 0%, hsla(225, 39%, 25%, 1) 0, transparent 50%);
37 | }
38 |
39 | .gradient-bg-footer {
40 | background-color: #0f0e13;
41 | background-image: radial-gradient(at 0% 100%, hsla(253, 16%, 7%, 1) 0, transparent 53%),
42 | radial-gradient(at 50% 150%, hsla(339, 49%, 30%, 1) 0, transparent 50%);
43 | }
44 |
45 | .blue-glassmorphism {
46 | background: rgb(39, 51, 89, 0.4);
47 | border-radius: 16px;
48 | box-shadow: 0 4px 30px rgba(0, 0, 0, 0.2);
49 | backdrop-filter: blur(5px);
50 | -webkit-backdrop-filter: blur(5px);
51 | border: 1px solid rgba(0, 0, 0, 0.3);
52 | }
53 |
54 | /* white glassmorphism */
55 | .white-glassmorphism {
56 | background: rgba(255, 255, 255, 0.05);
57 | border-radius: 16px;
58 | backdrop-filter: blur(5px);
59 | -webkit-backdrop-filter: blur(5px);
60 | border: 1px solid rgba(255, 255, 255, 0.3);
61 | }
62 |
63 | .eth-card {
64 | background-color: #a099ff;
65 | background-image: radial-gradient(at 83% 67%, rgb(152, 231, 156) 0, transparent 58%),
66 | radial-gradient(at 67% 20%, hsla(357, 94%, 71%, 1) 0, transparent 59%),
67 | radial-gradient(at 88% 35%, hsla(222, 81%, 65%, 1) 0, transparent 50%),
68 | radial-gradient(at 31% 91%, hsla(9, 61%, 61%, 1) 0, transparent 52%),
69 | radial-gradient(at 27% 71%, hsla(336, 91%, 65%, 1) 0, transparent 49%),
70 | radial-gradient(at 74% 89%, hsla(30, 98%, 65%, 1) 0, transparent 51%),
71 | radial-gradient(at 53% 75%, hsla(174, 94%, 68%, 1) 0, transparent 45%);
72 | }
73 |
74 | .text-gradient {
75 | background-color: #fff;
76 | background-image: radial-gradient(at 4% 36%, hsla(0, 0%, 100%, 1) 0, transparent 53%),
77 | radial-gradient(at 100% 60%, rgb(0, 0, 0) 0, transparent 50%);
78 | -webkit-background-clip: text;
79 | -webkit-text-fill-color: transparent;
80 | }
81 |
--------------------------------------------------------------------------------
/client/src/components/Transactions/Transactions.tsx:
--------------------------------------------------------------------------------
1 | import React, { useContext, useEffect } from 'react';
2 | import { TransactionContext } from '../../context/TransactionContext';
3 | import useFetch from '../../hooks/useFetch';
4 | import dummyData from '../../utils/dummyData';
5 | import { shortenAddress } from '../../utils/shortenAddress';
6 |
7 | interface TransactionCardProps {
8 | addressTo: string;
9 | addressFrom: string;
10 | amount: string;
11 | message: string;
12 | url: React.ImgHTMLAttributes['src'];
13 | timestamp: string;
14 | keyword?: string;
15 | }
16 |
17 | const TransactionCard = ({
18 | addressTo,
19 | addressFrom,
20 | timestamp,
21 | message,
22 | amount,
23 | url,
24 | keyword,
25 | }: TransactionCardProps) => {
26 | const gifUrl = useFetch({ keyword } as any);
27 | console.log('keyword: ', keyword);
28 | return (
29 |
37 |
38 |
62 | {gifUrl && (
63 |
68 | )}
69 |
70 |
73 |
74 |
75 | );
76 | };
77 |
78 | const Transactions = () => {
79 | const { currentAccount, transactions, transactionCount } = useContext(TransactionContext);
80 |
81 | return (
82 |
83 |
84 | {currentAccount ? (
85 |
Latest Transactions
86 | ) : (
87 |
88 | Connect your account to see the last changes
89 |
90 | )}
91 |
92 | {/* Connect your account to see last transactions */}
93 |
94 | {transactions.reverse().map((transaction, index) => {
95 | return ;
96 | })}
97 |
98 |
99 |
100 | );
101 | };
102 |
103 | export default Transactions;
104 |
--------------------------------------------------------------------------------
/client/src/components/Welcome/Welcome.tsx:
--------------------------------------------------------------------------------
1 | import React, { useContext, useEffect } from 'react';
2 | import { AiFillPlayCircle } from 'react-icons/ai';
3 | import { SiEthereum } from 'react-icons/si';
4 | import { BsInfoCircle } from 'react-icons/bs';
5 | import { Loader } from '..';
6 | import { TransactionContext } from '../../context/TransactionContext';
7 | import { shortenAddress } from '../../utils/shortenAddress';
8 |
9 | const commonStyles =
10 | 'min-h-[70px] sm:px-0 px-2 sm:min-w-[120px] flex justify-center items-center border-[0.5px] border-gray-400 text-sm font-light text-white';
11 |
12 | interface InputProps {
13 | placeholder: string;
14 | name: string;
15 | type: React.HTMLInputTypeAttribute;
16 | handleChange: (e: React.ChangeEvent, name: string) => void;
17 | value?: string;
18 | }
19 |
20 | const Input: React.FC = ({ placeholder, name, type, handleChange, value }) => (
21 | handleChange(e, name)}
26 | step='0.0001'
27 | value={value}
28 | className='w-full p-2 my-2 text-sm text-white bg-transparent border-none rounded-sm outline-none white-glassmorphism'
29 | />
30 | );
31 |
32 | const Welcome = () => {
33 | const { connectWallet, currentAccount, formData, isLoading, handleChange, sendTransactions } =
34 | useContext(TransactionContext);
35 |
36 | const handleSubmit = (e: React.MouseEvent) => {
37 | const { addressTo, amount, message, keyword } = formData;
38 |
39 | e.preventDefault();
40 |
41 | if (addressTo === '' || amount === '' || keyword === '' || message === '') {
42 | return alert('Please fill all fields');
43 | }
44 |
45 | sendTransactions();
46 | };
47 |
48 | const { addressTo, amount, message, keyword } = formData;
49 |
50 | useEffect(() => {
51 | console.log('data form: ', { addressTo, amount, message, keyword });
52 | }, [formData]);
53 |
54 | return (
55 |
56 |
57 |
58 |
59 | Send Crypto across world
60 |
61 |
62 | Explore the crypto world. Buy and sell cryptocurrencies easily on Krypto.
63 |
64 | {!currentAccount && (
65 |
69 | Connect Wallet
70 |
71 | )}
72 |
73 |
74 |
Reliability
75 |
Security
76 |
Ethereum
77 |
Web 3.0
78 |
Low fees
79 |
Blockchain
80 |
81 |
82 |
83 |
84 |
85 |
91 |
92 |
{shortenAddress(currentAccount)}
93 |
Ethereum
94 |
95 |
96 |
97 |
98 |
135 |
136 |
137 |
138 | );
139 | };
140 |
141 | export default Welcome;
142 |
--------------------------------------------------------------------------------
/client/src/context/TransactionContext.tsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect, createContext } from 'react';
2 | import { ethers } from 'ethers';
3 | import { contractABI, contractAddress } from '../utils/constants';
4 |
5 | interface TransactionContextProps {
6 | children: React.ReactNode;
7 | }
8 |
9 | type AppContextState = { addressTo: string; amount: string; keyword: string; message: string };
10 |
11 | const initialState = {
12 | connectWallet: () => {},
13 | currentAccount: '',
14 | handleChange: (e: React.ChangeEvent, name: string) => {},
15 | formData: { addressTo: '', amount: '', keyword: '', message: '' },
16 | setFormData: (state: AppContextState) => {},
17 | sendTransactions: () => {},
18 | transactions: [],
19 | isLoading: false,
20 | transactionCount: 0,
21 | };
22 |
23 | export const TransactionContext = createContext(initialState);
24 |
25 | const { ethereum }: any = window;
26 |
27 | const getEthereumContract = () => {
28 | const provider = new ethers.providers.Web3Provider(ethereum);
29 | const signer = provider.getSigner();
30 | const transactionsContract = new ethers.Contract(contractAddress, contractABI, signer);
31 |
32 | console.log('web3 ', {
33 | provider,
34 | signer,
35 | transactionsContract,
36 | });
37 |
38 | return transactionsContract;
39 | };
40 |
41 | const createEthereumContract = () => {
42 | const provider = new ethers.providers.Web3Provider(ethereum);
43 | const signer = provider.getSigner();
44 | const transactionsContract = new ethers.Contract(contractAddress, contractABI, signer);
45 |
46 | return transactionsContract;
47 | };
48 |
49 | export const TransactionsProvider = ({ children }: TransactionContextProps) => {
50 | const [currentAccount, setCurrentAccount] = useState('');
51 | const [formData, setFormData] = useState({ addressTo: '', amount: '', keyword: '', message: '' });
52 | const [isLoading, setIsLoading] = useState(false);
53 | const [transactionCount, setTransactionCount] = useState(
54 | Number(localStorage.getItem('transactionCount')) || 0
55 | );
56 | const [transactions, setTransactions] = useState([]);
57 |
58 | const handleChange = (e: React.ChangeEvent, name: string) => {
59 | setFormData((prev) => ({
60 | ...prev,
61 | [name]: e.target.value,
62 | }));
63 | };
64 |
65 | const getAllTransactions = async () => {
66 | try {
67 | if (ethereum) {
68 | const transactionsContract = createEthereumContract();
69 |
70 | const availableTransactions = await transactionsContract.getAllTransactions();
71 |
72 | const structuredTransactions = availableTransactions.map((transaction: any) => ({
73 | addressTo: transaction.receiver,
74 | addressFrom: transaction.from,
75 | timestamp: new Date(transaction.timestamp.toNumber() * 1000).toLocaleString(),
76 | message: transaction.message,
77 | keyword: transaction.keyword,
78 | amount: parseInt(transaction.amount._hex) / 10 ** 18,
79 | }));
80 |
81 | console.log('structuredTransactions: ', structuredTransactions);
82 |
83 | setTransactions(structuredTransactions);
84 | } else {
85 | console.log('Ethereum is not present');
86 | }
87 | } catch (error) {
88 | console.log(error);
89 | }
90 | };
91 |
92 | const checkIfTransactionExist = async () => {
93 | try {
94 | const transactionContract = getEthereumContract();
95 | const transactionCount = await transactionContract.getTransactionCount();
96 |
97 | window.localStorage.setItem('transactionCount', transactionCount);
98 | } catch (error) {
99 | console.log(error);
100 | throw new Error('No eth object!');
101 | }
102 | };
103 |
104 | const checkIfWalletConnected = async () => {
105 | try {
106 | if (!ethereum) {
107 | return alert('Please install metamask!');
108 | }
109 |
110 | const accounts: any[] = await ethereum.request({ method: 'eth_accounts' });
111 |
112 | if (accounts.length) {
113 | setCurrentAccount(accounts[0]);
114 |
115 | // get all transactions
116 | getAllTransactions();
117 | } else {
118 | console.log('No accounts found!');
119 | }
120 | } catch (error) {
121 | console.log('error ', error);
122 | }
123 | };
124 |
125 | const connectWallet = async () => {
126 | try {
127 | if (!ethereum) {
128 | return alert('Please install metamask!');
129 | }
130 | const accounts = await ethereum.request({ method: 'eth_requestAccounts' });
131 |
132 | setCurrentAccount(accounts[0]);
133 | } catch (e) {
134 | console.log('error: ', e);
135 | throw new Error('No eth object!');
136 | }
137 | };
138 |
139 | const sendTransactions = async () => {
140 | try {
141 | if (!ethereum) {
142 | return alert('Please install metamask!');
143 | }
144 | const { addressTo, amount, message, keyword } = formData;
145 | const transactionContract = getEthereumContract();
146 | const parsedAmount = ethers.utils.parseEther(amount);
147 | await ethereum.request({
148 | method: 'eth_sendTransaction',
149 | params: [
150 | {
151 | from: currentAccount,
152 | to: addressTo,
153 | gas: '0x5208', // 21000
154 | value: parsedAmount._hex,
155 | },
156 | ],
157 | });
158 |
159 | const transactionHash = await transactionContract.addToBlockChain(
160 | addressTo,
161 | parsedAmount,
162 | message,
163 | keyword
164 | );
165 |
166 | setIsLoading(true);
167 |
168 | console.log(`Loading - ${transactionHash.hash}`);
169 |
170 | await transactionHash.wait();
171 |
172 | setIsLoading(false);
173 |
174 | console.log(`Success - ${transactionHash.hash}`);
175 |
176 | const transactionCount = await transactionContract.getTransactionCount();
177 |
178 | setTransactionCount(transactionCount.toNumber());
179 |
180 | window.location.reload();
181 | } catch (error) {
182 | console.log('error:', error);
183 | }
184 | };
185 |
186 | useEffect(() => {
187 | checkIfWalletConnected();
188 | checkIfTransactionExist();
189 | }, [transactionCount]);
190 |
191 | return (
192 |
204 | {children}
205 |
206 | );
207 | };
208 |
--------------------------------------------------------------------------------
/client/images/hello.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/client/images/animated.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/client/src/utils/Transactions.json:
--------------------------------------------------------------------------------
1 | {
2 | "_format": "hh-sol-artifact-1",
3 | "contractName": "Transactions",
4 | "sourceName": "contracts/Transactions.sol",
5 | "abi": [
6 | {
7 | "anonymous": false,
8 | "inputs": [
9 | {
10 | "indexed": false,
11 | "internalType": "address",
12 | "name": "from",
13 | "type": "address"
14 | },
15 | {
16 | "indexed": false,
17 | "internalType": "address",
18 | "name": "receiver",
19 | "type": "address"
20 | },
21 | {
22 | "indexed": false,
23 | "internalType": "uint256",
24 | "name": "amount",
25 | "type": "uint256"
26 | },
27 | {
28 | "indexed": false,
29 | "internalType": "string",
30 | "name": "message",
31 | "type": "string"
32 | },
33 | {
34 | "indexed": false,
35 | "internalType": "uint256",
36 | "name": "timestamp",
37 | "type": "uint256"
38 | },
39 | {
40 | "indexed": false,
41 | "internalType": "string",
42 | "name": "keyword",
43 | "type": "string"
44 | }
45 | ],
46 | "name": "Transfer",
47 | "type": "event"
48 | },
49 | {
50 | "inputs": [
51 | {
52 | "internalType": "address payable",
53 | "name": "receiver",
54 | "type": "address"
55 | },
56 | {
57 | "internalType": "uint256",
58 | "name": "amount",
59 | "type": "uint256"
60 | },
61 | {
62 | "internalType": "string",
63 | "name": "message",
64 | "type": "string"
65 | },
66 | {
67 | "internalType": "string",
68 | "name": "keyword",
69 | "type": "string"
70 | }
71 | ],
72 | "name": "addToBlockChain",
73 | "outputs": [],
74 | "stateMutability": "nonpayable",
75 | "type": "function"
76 | },
77 | {
78 | "inputs": [],
79 | "name": "getAllTransactions",
80 | "outputs": [
81 | {
82 | "components": [
83 | {
84 | "internalType": "address",
85 | "name": "from",
86 | "type": "address"
87 | },
88 | {
89 | "internalType": "address",
90 | "name": "receiver",
91 | "type": "address"
92 | },
93 | {
94 | "internalType": "uint256",
95 | "name": "amount",
96 | "type": "uint256"
97 | },
98 | {
99 | "internalType": "string",
100 | "name": "message",
101 | "type": "string"
102 | },
103 | {
104 | "internalType": "uint256",
105 | "name": "timestamp",
106 | "type": "uint256"
107 | },
108 | {
109 | "internalType": "string",
110 | "name": "keyword",
111 | "type": "string"
112 | }
113 | ],
114 | "internalType": "struct Transactions.TransferStruct[]",
115 | "name": "",
116 | "type": "tuple[]"
117 | }
118 | ],
119 | "stateMutability": "view",
120 | "type": "function"
121 | },
122 | {
123 | "inputs": [],
124 | "name": "getTransactionCount",
125 | "outputs": [
126 | {
127 | "internalType": "uint256",
128 | "name": "",
129 | "type": "uint256"
130 | }
131 | ],
132 | "stateMutability": "view",
133 | "type": "function"
134 | }
135 | ],
136 | "bytecode": "0x608060405234801561001057600080fd5b50610c0d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806327506f53146100465780632e7700f014610064578063b2da096014610082575b600080fd5b61004e61009e565b60405161005b91906108b9565b60405180910390f35b61006c6102e1565b60405161007991906108db565b60405180910390f35b61009c600480360381019061009791906105e1565b6102ea565b005b60606001805480602002602001604051908101604052809291908181526020016000905b828210156102d857838290600052602060002090600602016040518060c00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015481526020016003820180546101ab90610ad9565b80601f01602080910402602001604051908101604052809291908181526020018280546101d790610ad9565b80156102245780601f106101f957610100808354040283529160200191610224565b820191906000526020600020905b81548152906001019060200180831161020757829003601f168201915b505050505081526020016004820154815260200160058201805461024790610ad9565b80601f016020809104026020016040519081016040528092919081815260200182805461027390610ad9565b80156102c05780601f10610295576101008083540402835291602001916102c0565b820191906000526020600020905b8154815290600101906020018083116102a357829003601f168201915b505050505081525050815260200190600101906100c2565b50505050905090565b60008054905090565b60016000808282546102fc91906109bd565b9250508190555060016040518060c001604052803373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200185815260200184815260200142815260200183815250908060018154018082558091505060019003906000526020600020906006020160009091909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020155606082015181600301908051906020019061043b9291906104ac565b506080820151816004015560a08201518160050190805190602001906104629291906104ac565b5050507f416cfa4330a4565f45c2fd2dd4826a83a37443aba2ce6f79477c7355afac35fa33858585428660405161049e9695949392919061084a565b60405180910390a150505050565b8280546104b890610ad9565b90600052602060002090601f0160209004810192826104da5760008555610521565b82601f106104f357805160ff1916838001178555610521565b82800160010185558215610521579182015b82811115610520578251825591602001919060010190610505565b5b50905061052e9190610532565b5090565b5b8082111561054b576000816000905550600101610533565b5090565b600061056261055d84610927565b6108f6565b90508281526020810184848401111561057a57600080fd5b610585848285610a97565b509392505050565b60008135905061059c81610ba9565b92915050565b600082601f8301126105b357600080fd5b81356105c384826020860161054f565b91505092915050565b6000813590506105db81610bc0565b92915050565b600080600080608085870312156105f757600080fd5b60006106058782880161058d565b9450506020610616878288016105cc565b935050604085013567ffffffffffffffff81111561063357600080fd5b61063f878288016105a2565b925050606085013567ffffffffffffffff81111561065c57600080fd5b610668878288016105a2565b91505092959194509250565b6000610680838361079c565b905092915050565b61069181610a61565b82525050565b6106a081610a13565b82525050565b6106af81610a13565b82525050565b60006106c082610967565b6106ca818561098a565b9350836020820285016106dc85610957565b8060005b8581101561071857848403895281516106f98582610674565b94506107048361097d565b925060208a019950506001810190506106e0565b50829750879550505050505092915050565b600061073582610972565b61073f818561099b565b935061074f818560208601610aa6565b61075881610b98565b840191505092915050565b600061076e82610972565b61077881856109ac565b9350610788818560208601610aa6565b61079181610b98565b840191505092915050565b600060c0830160008301516107b46000860182610697565b5060208301516107c76020860182610697565b5060408301516107da604086018261082c565b50606083015184820360608601526107f2828261072a565b9150506080830151610807608086018261082c565b5060a083015184820360a086015261081f828261072a565b9150508091505092915050565b61083581610a57565b82525050565b61084481610a57565b82525050565b600060c08201905061085f60008301896106a6565b61086c6020830188610688565b610879604083018761083b565b818103606083015261088b8186610763565b905061089a608083018561083b565b81810360a08301526108ac8184610763565b9050979650505050505050565b600060208201905081810360008301526108d381846106b5565b905092915050565b60006020820190506108f0600083018461083b565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561091d5761091c610b69565b5b8060405250919050565b600067ffffffffffffffff82111561094257610941610b69565b5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b60006109c882610a57565b91506109d383610a57565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610a0857610a07610b0b565b5b828201905092915050565b6000610a1e82610a37565b9050919050565b6000610a3082610a37565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000610a6c82610a73565b9050919050565b6000610a7e82610a85565b9050919050565b6000610a9082610a37565b9050919050565b82818337600083830152505050565b60005b83811015610ac4578082015181840152602081019050610aa9565b83811115610ad3576000848401525b50505050565b60006002820490506001821680610af157607f821691505b60208210811415610b0557610b04610b3a565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b610bb281610a25565b8114610bbd57600080fd5b50565b610bc981610a57565b8114610bd457600080fd5b5056fea26469706673582212205396c81e995d22bbc2272c12cc4998aa414c5cabf2cd94f932fbd4596978663464736f6c63430008000033",
137 | "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806327506f53146100465780632e7700f014610064578063b2da096014610082575b600080fd5b61004e61009e565b60405161005b91906108b9565b60405180910390f35b61006c6102e1565b60405161007991906108db565b60405180910390f35b61009c600480360381019061009791906105e1565b6102ea565b005b60606001805480602002602001604051908101604052809291908181526020016000905b828210156102d857838290600052602060002090600602016040518060c00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015481526020016003820180546101ab90610ad9565b80601f01602080910402602001604051908101604052809291908181526020018280546101d790610ad9565b80156102245780601f106101f957610100808354040283529160200191610224565b820191906000526020600020905b81548152906001019060200180831161020757829003601f168201915b505050505081526020016004820154815260200160058201805461024790610ad9565b80601f016020809104026020016040519081016040528092919081815260200182805461027390610ad9565b80156102c05780601f10610295576101008083540402835291602001916102c0565b820191906000526020600020905b8154815290600101906020018083116102a357829003601f168201915b505050505081525050815260200190600101906100c2565b50505050905090565b60008054905090565b60016000808282546102fc91906109bd565b9250508190555060016040518060c001604052803373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff16815260200185815260200184815260200142815260200183815250908060018154018082558091505060019003906000526020600020906006020160009091909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020155606082015181600301908051906020019061043b9291906104ac565b506080820151816004015560a08201518160050190805190602001906104629291906104ac565b5050507f416cfa4330a4565f45c2fd2dd4826a83a37443aba2ce6f79477c7355afac35fa33858585428660405161049e9695949392919061084a565b60405180910390a150505050565b8280546104b890610ad9565b90600052602060002090601f0160209004810192826104da5760008555610521565b82601f106104f357805160ff1916838001178555610521565b82800160010185558215610521579182015b82811115610520578251825591602001919060010190610505565b5b50905061052e9190610532565b5090565b5b8082111561054b576000816000905550600101610533565b5090565b600061056261055d84610927565b6108f6565b90508281526020810184848401111561057a57600080fd5b610585848285610a97565b509392505050565b60008135905061059c81610ba9565b92915050565b600082601f8301126105b357600080fd5b81356105c384826020860161054f565b91505092915050565b6000813590506105db81610bc0565b92915050565b600080600080608085870312156105f757600080fd5b60006106058782880161058d565b9450506020610616878288016105cc565b935050604085013567ffffffffffffffff81111561063357600080fd5b61063f878288016105a2565b925050606085013567ffffffffffffffff81111561065c57600080fd5b610668878288016105a2565b91505092959194509250565b6000610680838361079c565b905092915050565b61069181610a61565b82525050565b6106a081610a13565b82525050565b6106af81610a13565b82525050565b60006106c082610967565b6106ca818561098a565b9350836020820285016106dc85610957565b8060005b8581101561071857848403895281516106f98582610674565b94506107048361097d565b925060208a019950506001810190506106e0565b50829750879550505050505092915050565b600061073582610972565b61073f818561099b565b935061074f818560208601610aa6565b61075881610b98565b840191505092915050565b600061076e82610972565b61077881856109ac565b9350610788818560208601610aa6565b61079181610b98565b840191505092915050565b600060c0830160008301516107b46000860182610697565b5060208301516107c76020860182610697565b5060408301516107da604086018261082c565b50606083015184820360608601526107f2828261072a565b9150506080830151610807608086018261082c565b5060a083015184820360a086015261081f828261072a565b9150508091505092915050565b61083581610a57565b82525050565b61084481610a57565b82525050565b600060c08201905061085f60008301896106a6565b61086c6020830188610688565b610879604083018761083b565b818103606083015261088b8186610763565b905061089a608083018561083b565b81810360a08301526108ac8184610763565b9050979650505050505050565b600060208201905081810360008301526108d381846106b5565b905092915050565b60006020820190506108f0600083018461083b565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561091d5761091c610b69565b5b8060405250919050565b600067ffffffffffffffff82111561094257610941610b69565b5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b60006109c882610a57565b91506109d383610a57565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610a0857610a07610b0b565b5b828201905092915050565b6000610a1e82610a37565b9050919050565b6000610a3082610a37565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000610a6c82610a73565b9050919050565b6000610a7e82610a85565b9050919050565b6000610a9082610a37565b9050919050565b82818337600083830152505050565b60005b83811015610ac4578082015181840152602081019050610aa9565b83811115610ad3576000848401525b50505050565b60006002820490506001821680610af157607f821691505b60208210811415610b0557610b04610b3a565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b610bb281610a25565b8114610bbd57600080fd5b50565b610bc981610a57565b8114610bd457600080fd5b5056fea26469706673582212205396c81e995d22bbc2272c12cc4998aa414c5cabf2cd94f932fbd4596978663464736f6c63430008000033",
138 | "linkReferences": {},
139 | "deployedLinkReferences": {}
140 | }
141 |
--------------------------------------------------------------------------------