diff --git a/README.md b/README.md index fc37ff2..6fc581a 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,28 @@ -
-

🔏 CarnationFM

- -![Screenshot 2024-05-26 105040](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/4f0eaaac-e9d8-46f1-8b8f-9346535414d9) -
- -Established systems are failing. - -Carnation is an experiment in decentralized and encrypted communication with a focus on music as transport vessel caring hidden messages. It empowers users to broadcast their voice and coordinate with others securely and privately all while safeguarding their anonymity. -Contribute with an audio file (wav, flac) and weave in an encrypted message into to subsonic frequencies. This hidden channel allows for discreet communication. - -![user flow (2)](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/135f25c7-0fb4-402a-b1a0-7464657b0ce7) - -Carnation prioritizes anonymity, letting your voice be heard without compromising your safety. It thrives on community. It's a space for collaboration, where people can unite and coordinate towards a shared vision. -Imagine the underprivileged individuals and collectives whose message is embedded in the music, broadcasted for all to hear, yet only those who know where to look can decipher it. - -**Check out our slides - [here](https://github.com/Tranquil-Flow/carnation-radio/blob/main/SLIDES.md)

** -**Check out our demo - [here](https://kapture-debelg-debelgs-projects.vercel.app/)

** - -We have created [CLI](https://github.com/Tranquil-Flow/carnation-radio/tree/main/whistle) for encryption of the message into the wav file which is then uploaded onto **ETHSwarm** decentralized data storage. We have deployed our frontend via **Scaffold-ETH2** and deployed our smart contracts for auction of the 24h playlist NFT (funding mechanism for data storage) on ETHSepolia. - -Details of the subsonic steganography scheme and instructions can be explored - [here](https://github.com/Tranquil-Flow/carnation-radio/blob/subsonic-steganography/steganography/README.md) - -![tech stack (2)](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/874b9f9b-c39a-48e0-b6eb-5687fec31f51) - -Auction.sol on Sepolia - [here](https://sepolia.etherscan.io/address/0x4894421a7c0bc369a5c10ddbaf4dbc7cf3b72ae5#code) - -AudioSetNFT.sol on Sepolia - [here](https://sepolia.etherscan.io/address/0x75993080804d364419445175c5a543eda6a20bb0#code) +
+

🔏 CarnationFM

+ +![Screenshot 2024-05-26 105040](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/4f0eaaac-e9d8-46f1-8b8f-9346535414d9) +
+ +Established systems are failing. + +Carnation is an experiment in decentralized and encrypted communication with a focus on music as transport vessel caring hidden messages. It empowers users to broadcast their voice and coordinate with others securely and privately all while safeguarding their anonymity. +Contribute with an audio file (wav, flac) and weave in an encrypted message into to subsonic frequencies. This hidden channel allows for discreet communication. + +![user flow (2)](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/135f25c7-0fb4-402a-b1a0-7464657b0ce7) + +Carnation prioritizes anonymity, letting your voice be heard without compromising your safety. It thrives on community. It's a space for collaboration, where people can unite and coordinate towards a shared vision. +Imagine the underprivileged individuals and collectives whose message is embedded in the music, broadcasted for all to hear, yet only those who know where to look can decipher it. + +**Check out our slides - [here](https://github.com/Tranquil-Flow/carnation-radio/blob/main/SLIDES.md)

** +**Check out our demo - [here](https://kapture-debelg-debelgs-projects.vercel.app/)

** + +We have created [CLI](https://github.com/Tranquil-Flow/carnation-radio/tree/main/whistle) for encryption of the message into the wav file which is then uploaded onto **ETHSwarm** decentralized data storage. We have deployed our frontend via **Scaffold-ETH2** and deployed our smart contracts for auction of the 24h playlist NFT (funding mechanism for data storage) on ETHSepolia. + +Details of the subsonic steganography scheme and instructions can be explored - [here](https://github.com/Tranquil-Flow/carnation-radio/blob/subsonic-steganography/steganography/README.md) + +![tech stack (2)](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/874b9f9b-c39a-48e0-b6eb-5687fec31f51) + +Auction.sol on Sepolia - [here](https://sepolia.etherscan.io/address/0x4894421a7c0bc369a5c10ddbaf4dbc7cf3b72ae5#code) + +AudioSetNFT.sol on Sepolia - [here](https://sepolia.etherscan.io/address/0x75993080804d364419445175c5a543eda6a20bb0#code) diff --git a/SLIDES.md b/SLIDES.md index 151b21a..60d1c47 100644 --- a/SLIDES.md +++ b/SLIDES.md @@ -1,9 +1,9 @@ -
-

CarnationFM

- -![slide1 (2)](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/b6a920f2-4061-498c-81e1-c89827636140) -![why (2)](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/e5c71b8c-41e4-48d8-ba98-28a8704473b5) -![what (2)](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/52677190-bad4-4b2c-a65d-c815d761b08e) -![ui](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/5b9e1893-9916-47a6-89a4-efb888ac752d) -![user flow (2)](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/79402701-3dda-4273-a848-e51590dc87b7) -![tech stack (2)](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/e45b96ad-d924-4ebe-bc8a-fd2f65aa722d) +
+

CarnationFM

+ +![slide1 (2)](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/b6a920f2-4061-498c-81e1-c89827636140) +![why (2)](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/e5c71b8c-41e4-48d8-ba98-28a8704473b5) +![what (2)](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/52677190-bad4-4b2c-a65d-c815d761b08e) +![ui](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/5b9e1893-9916-47a6-89a4-efb888ac752d) +![user flow (2)](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/79402701-3dda-4273-a848-e51590dc87b7) +![tech stack (2)](https://github.com/Tranquil-Flow/carnation-radio/assets/101796507/e45b96ad-d924-4ebe-bc8a-fd2f65aa722d) diff --git a/packages/hardhat/contracts/Auction.sol b/packages/hardhat/contracts/Auction.sol index e3f04fd..9f7d090 100644 --- a/packages/hardhat/contracts/Auction.sol +++ b/packages/hardhat/contracts/Auction.sol @@ -88,29 +88,6 @@ contract Auction is ReentrancyGuard { emit BidRemoved(_audioSlotID, msg.sender); } - function editBid(uint _audioSlotID) external payable nonReentrant { - AudioSlot storage slot = audioSlots[_audioSlotID]; - Bid storage existingBid = bids[_audioSlotID][msg.sender]; - - // Check the auction is ongoing - if (block.timestamp < slot.auctionStartTime) {revert AuctionNotStarted();} - if (block.timestamp > slot.auctionStartTime + auctionLength) {revert AuctionAlreadyEnded();} - - // Check bid amount is greater than zero - if (msg.value == 0) {revert BidAmountZero();} - - // Transfer the bid amount to the contract - (bool success, ) = address(this).call{value: msg.value}(""); - if (!success) {revert ETHTransferInFailed();} - - // Update the bid amount - uint newBidAmount = existingBid.bidAmount + msg.value; - existingBid.bidAmount = newBidAmount; - - emit BidRemoved(_audioSlotID, msg.sender); - emit BidPlaced(_audioSlotID, msg.sender, newBidAmount); - } - function startAuction(uint _audioSlotID, string calldata _audioName) external { AudioSlot storage slot = audioSlots[_audioSlotID]; diff --git a/packages/hardhat/deploy/00_deploy_your_contract.ts b/packages/hardhat/deploy/00_deploy_your_contract.ts index 4b91f71..6500f45 100644 --- a/packages/hardhat/deploy/00_deploy_your_contract.ts +++ b/packages/hardhat/deploy/00_deploy_your_contract.ts @@ -1,47 +1,47 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DeployFunction } from "hardhat-deploy/types"; - -const deployContracts: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployer } = await hre.getNamedAccounts(); - const { deploy } = hre.deployments; - const { ethers } = hre; - - // Deploy the Auction contract - const auctionDeployment = await deploy("Auction", { - from: deployer, - log: true, - autoMine: true, - }); - - const auctionContractAddress = auctionDeployment.address; - if (!auctionContractAddress) { - throw new Error("Failed to get Auction contract address"); - } - - // Deploy the AudioSetNFT contract with the Auction contract address as an argument - const audioSetNFTDeployment = await deploy("AudioSetNFT", { - from: deployer, - args: [auctionContractAddress], - log: true, - autoMine: true, - }); - - const audioSetNFTContractAddress = audioSetNFTDeployment.address; - if (!audioSetNFTContractAddress) { - throw new Error("Failed to get AudioSetNFT contract address"); - } - - // Get the Auction contract instance - const auctionContract = await ethers.getContractAt("Auction", auctionContractAddress); - - // Call the defineNFTcontract function on the Auction contract with the address of the deployed AudioSetNFT contract - const tx = await auctionContract.defineNFTcontract(audioSetNFTContractAddress); - await tx.wait(); - - console.log(`Auction contract deployed at: ${auctionContractAddress}`); - console.log(`AudioSetNFT contract deployed at: ${audioSetNFTContractAddress}`); -}; - -export default deployContracts; - -deployContracts.tags = ["Auction", "AudioSetNFT"]; +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +const deployContracts: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployer } = await hre.getNamedAccounts(); + const { deploy } = hre.deployments; + const { ethers } = hre; + + // Deploy the Auction contract + const auctionDeployment = await deploy("Auction", { + from: deployer, + log: true, + autoMine: true, + }); + + const auctionContractAddress = auctionDeployment.address; + if (!auctionContractAddress) { + throw new Error("Failed to get Auction contract address"); + } + + // Deploy the AudioSetNFT contract with the Auction contract address as an argument + const audioSetNFTDeployment = await deploy("AudioSetNFT", { + from: deployer, + args: [auctionContractAddress], + log: true, + autoMine: true, + }); + + const audioSetNFTContractAddress = audioSetNFTDeployment.address; + if (!audioSetNFTContractAddress) { + throw new Error("Failed to get AudioSetNFT contract address"); + } + + // Get the Auction contract instance + const auctionContract = await ethers.getContractAt("Auction", auctionContractAddress); + + // Call the defineNFTcontract function on the Auction contract with the address of the deployed AudioSetNFT contract + const tx = await auctionContract.defineNFTcontract(audioSetNFTContractAddress); + await tx.wait(); + + console.log(`Auction contract deployed at: ${auctionContractAddress}`); + console.log(`AudioSetNFT contract deployed at: ${audioSetNFTContractAddress}`); +}; + +export default deployContracts; + +deployContracts.tags = ["Auction", "AudioSetNFT"]; diff --git a/packages/nextjs/app/page-old.tsx b/packages/nextjs/app/page-old.tsx deleted file mode 100644 index fcca994..0000000 --- a/packages/nextjs/app/page-old.tsx +++ /dev/null @@ -1,71 +0,0 @@ -"use client"; - -import Link from "next/link"; -import type { NextPage } from "next"; -import { useAccount } from "wagmi"; -import { BugAntIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline"; -import { Address } from "~~/components/scaffold-eth"; - -const Home: NextPage = () => { - const { address: connectedAddress } = useAccount(); - - return ( - <> -
-
-

- Welcome to - Scaffold-ETH 2 -

-
-

Connected Address:

-
-
-

- Get started by editing{" "} - - packages/nextjs/app/page.tsx - -

-

- Edit your smart contract{" "} - - YourContract.sol - {" "} - in{" "} - - packages/hardhat/contracts - -

-
- -
-
-
- -

- Tinker with your smart contract using the{" "} - - Debug Contracts - {" "} - tab. -

-
-
- -

- Explore your local transactions with the{" "} - - Block Explorer - {" "} - tab. -

-
-
-
-
- - ); -}; - -export default Home; diff --git a/packages/nextjs/app/page.tsx b/packages/nextjs/app/page.tsx index dcf2c5e..01601f7 100644 --- a/packages/nextjs/app/page.tsx +++ b/packages/nextjs/app/page.tsx @@ -1,36 +1,71 @@ -"use client"; -import React, { useState } from 'react'; -import '../styles/App.css'; -import Navbar from '../components/Navbar'; -import AuctionView from '../components/AuctionView'; -// import background from '../components/assets/background.svg'; - -import Link from "next/link"; -import type { NextPage } from "next"; -import { useAccount } from "wagmi"; -import { BugAntIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline"; -import { Address } from "~~/components/scaffold-eth"; - -const Home: NextPage = () => { - const { address: connectedAddress } = useAccount(); - - const [view, setView] = useState('listen'); - - const handleNavClick = (view) => { - setView(view); - }; - - return ( -
- {/*
*/} - -
- {view === 'auction' && } - {/* Add the listen view component here */} -
-
- ); - -}; - -export default Home; \ No newline at end of file +"use client"; + +import Link from "next/link"; +import type { NextPage } from "next"; +import { useAccount } from "wagmi"; +import { BugAntIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline"; +import { Address } from "~~/components/scaffold-eth"; + +const Home: NextPage = () => { + const { address: connectedAddress } = useAccount(); + + return ( + <> +
+
+

+ Welcome to + Scaffold-ETH 2 +

+
+

Connected Address:

+
+
+

+ Get started by editing{" "} + + packages/nextjs/app/page.tsx + +

+

+ Edit your smart contract{" "} + + YourContract.sol + {" "} + in{" "} + + packages/hardhat/contracts + +

+
+ +
+
+
+ +

+ Tinker with your smart contract using the{" "} + + Debug Contracts + {" "} + tab. +

+
+
+ +

+ Explore your local transactions with the{" "} + + Block Explorer + {" "} + tab. +

+
+
+
+
+ + ); +}; + +export default Home; diff --git a/packages/nextjs/components/AuctionView.tsx b/packages/nextjs/components/AuctionView.tsx index ecb8a4a..50bff01 100644 --- a/packages/nextjs/components/AuctionView.tsx +++ b/packages/nextjs/components/AuctionView.tsx @@ -1,45 +1,45 @@ -import React from 'react'; -import '../styles/AuctionView.css'; - -const AuctionView = () => { - const tracks = ['Track 1', 'Track 2', 'Track 3']; // Example tracks - const bids = [ - { ordinal: 1, username: 'user1', amount: '$100' }, - { ordinal: 2, username: 'user2', amount: '$90' }, - ]; - - return ( -
-
-
-
AMOUNT
-
BID
-
-
EDIT BID
-
WITHDRAW
-
-
-
- {tracks.map((track, index) => ( -
- {track} -
- ))} -
-
-
-
BIDS:
-
- {bids.map((bid, index) => ( -
- {bid.ordinal}. {bid.username} {bid.amount} -
- ))} -
-
END AUCTION
-
-
- ); -}; - -export default AuctionView; +import React from "react"; +import "../styles/AuctionView.css"; + +const AuctionView = () => { + const tracks = ["Track 1", "Track 2", "Track 3"]; // Example tracks + const bids = [ + { ordinal: 1, username: "user1", amount: "$100" }, + { ordinal: 2, username: "user2", amount: "$90" }, + ]; + + return ( +
+
+
+
AMOUNT
+
BID
+
+
EDIT BID
+
WITHDRAW
+
+
+
+ {tracks.map((track, index) => ( +
+ {track} +
+ ))} +
+
+
+
BIDS:
+
+ {bids.map((bid, index) => ( +
+ {bid.ordinal}. {bid.username} {bid.amount} +
+ ))} +
+
END AUCTION
+
+
+ ); +}; + +export default AuctionView; diff --git a/packages/nextjs/components/Footer.tsx b/packages/nextjs/components/Footer.tsx index 7aac136..989f45a 100644 --- a/packages/nextjs/components/Footer.tsx +++ b/packages/nextjs/components/Footer.tsx @@ -1,80 +1,80 @@ -import React from "react"; -import Link from "next/link"; -import { hardhat } from "viem/chains"; -import { CurrencyDollarIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline"; -import { HeartIcon } from "@heroicons/react/24/outline"; -import { SwitchTheme } from "~~/components/SwitchTheme"; -import { BuidlGuidlLogo } from "~~/components/assets/BuidlGuidlLogo"; -import { Faucet } from "~~/components/scaffold-eth"; -import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork"; -import { useGlobalState } from "~~/services/store/store"; - -/** - * Site footer - */ -export const Footer = () => { - const nativeCurrencyPrice = useGlobalState(state => state.nativeCurrencyPrice); - const { targetNetwork } = useTargetNetwork(); - const isLocalNetwork = targetNetwork.id === hardhat.id; - - return ( -
-
-
-
- {nativeCurrencyPrice > 0 && ( -
-
- - {nativeCurrencyPrice} -
-
- )} - {isLocalNetwork && ( - <> - - - - Block Explorer - - - )} -
- -
-
-
- -
-
- ); -}; +import React from "react"; +import Link from "next/link"; +import { hardhat } from "viem/chains"; +import { CurrencyDollarIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline"; +import { HeartIcon } from "@heroicons/react/24/outline"; +import { SwitchTheme } from "~~/components/SwitchTheme"; +import { BuidlGuidlLogo } from "~~/components/assets/BuidlGuidlLogo"; +import { Faucet } from "~~/components/scaffold-eth"; +import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork"; +import { useGlobalState } from "~~/services/store/store"; + +/** + * Site footer + */ +export const Footer = () => { + const nativeCurrencyPrice = useGlobalState(state => state.nativeCurrencyPrice); + const { targetNetwork } = useTargetNetwork(); + const isLocalNetwork = targetNetwork.id === hardhat.id; + + return ( +
+
+
+
+ {nativeCurrencyPrice > 0 && ( +
+
+ + {nativeCurrencyPrice} +
+
+ )} + {isLocalNetwork && ( + <> + + + + Block Explorer + + + )} +
+ +
+
+
+ +
+
+ ); +}; diff --git a/packages/nextjs/components/Header.tsx b/packages/nextjs/components/Header.tsx index f24a1de..6e99d54 100644 --- a/packages/nextjs/components/Header.tsx +++ b/packages/nextjs/components/Header.tsx @@ -1,110 +1,110 @@ -"use client"; - -import React, { useCallback, useRef, useState } from "react"; -import Image from "next/image"; -import Link from "next/link"; -import { usePathname } from "next/navigation"; -import { Bars3Icon, BugAntIcon } from "@heroicons/react/24/outline"; -import { FaucetButton, RainbowKitCustomConnectButton } from "~~/components/scaffold-eth"; -import { useOutsideClick } from "~~/hooks/scaffold-eth"; - -type HeaderMenuLink = { - label: string; - href: string; - icon?: React.ReactNode; -}; - -export const menuLinks: HeaderMenuLink[] = [ - { - label: "Home", - href: "/", - }, - { - label: "Debug Contracts", - href: "/debug", - icon: , - }, -]; - -export const HeaderMenuLinks = () => { - const pathname = usePathname(); - - return ( - <> - {menuLinks.map(({ label, href, icon }) => { - const isActive = pathname === href; - return ( -
  • - - {icon} - {label} - -
  • - ); - })} - - ); -}; - -/** - * Site header - */ -export const Header = () => { - const [isDrawerOpen, setIsDrawerOpen] = useState(false); - const burgerMenuRef = useRef(null); - useOutsideClick( - burgerMenuRef, - useCallback(() => setIsDrawerOpen(false), []), - ); - - return ( -
    -
    -
    - - {isDrawerOpen && ( -
      { - setIsDrawerOpen(false); - }} - > - -
    - )} -
    - -
    - SE2 logo -
    -
    - Scaffold-ETH - Ethereum dev stack -
    - -
      - -
    -
    -
    - - -
    -
    - ); -}; +"use client"; + +import React, { useCallback, useRef, useState } from "react"; +import Image from "next/image"; +import Link from "next/link"; +import { usePathname } from "next/navigation"; +import { Bars3Icon, BugAntIcon } from "@heroicons/react/24/outline"; +import { FaucetButton, RainbowKitCustomConnectButton } from "~~/components/scaffold-eth"; +import { useOutsideClick } from "~~/hooks/scaffold-eth"; + +type HeaderMenuLink = { + label: string; + href: string; + icon?: React.ReactNode; +}; + +export const menuLinks: HeaderMenuLink[] = [ + { + label: "Home", + href: "/", + }, + { + label: "Debug Contracts", + href: "/debug", + icon: , + }, +]; + +export const HeaderMenuLinks = () => { + const pathname = usePathname(); + + return ( + <> + {menuLinks.map(({ label, href, icon }) => { + const isActive = pathname === href; + return ( +
  • + + {icon} + {label} + +
  • + ); + })} + + ); +}; + +/** + * Site header + */ +export const Header = () => { + const [isDrawerOpen, setIsDrawerOpen] = useState(false); + const burgerMenuRef = useRef(null); + useOutsideClick( + burgerMenuRef, + useCallback(() => setIsDrawerOpen(false), []), + ); + + return ( +
    +
    +
    + + {isDrawerOpen && ( +
      { + setIsDrawerOpen(false); + }} + > + +
    + )} +
    + +
    + SE2 logo +
    +
    + Scaffold-ETH + Ethereum dev stack +
    + +
      + +
    +
    +
    + + +
    +
    + ); +}; diff --git a/packages/nextjs/components/Navbar.jsx b/packages/nextjs/components/Navbar.jsx index 341c2f9..3a6dc06 100644 --- a/packages/nextjs/components/Navbar.jsx +++ b/packages/nextjs/components/Navbar.jsx @@ -1,26 +1,26 @@ -import React from 'react'; -// import '../../styles/Navbar.css'; -import logo from './assets/carnation-logo.svg'; - -const Navbar = ({ currentView, onNavClick }) => { - return ( -
    - Carnation Logo -
    - {['listen', 'download', 'auction'].map((item) => ( -
    onNavClick(item)} - > - {item} -
    - ))} -
    -
    - ); -}; - -export default Navbar; - - +import React from 'react'; +// import '../../styles/Navbar.css'; +import logo from './assets/carnation-logo.svg'; + +const Navbar = ({ currentView, onNavClick }) => { + return ( +
    + Carnation Logo +
    + {['listen', 'download', 'auction'].map((item) => ( +
    onNavClick(item)} + > + {item} +
    + ))} +
    +
    + ); +}; + +export default Navbar; + + diff --git a/packages/nextjs/components/assets/background.svg b/packages/nextjs/components/assets/background.svg index 6281457..693e785 100644 --- a/packages/nextjs/components/assets/background.svg +++ b/packages/nextjs/components/assets/background.svg @@ -1,3 +1,3 @@ - - - + + + diff --git a/packages/nextjs/components/assets/carnation-logo.svg b/packages/nextjs/components/assets/carnation-logo.svg index 6d7eb6c..6ab3df4 100644 --- a/packages/nextjs/components/assets/carnation-logo.svg +++ b/packages/nextjs/components/assets/carnation-logo.svg @@ -1,3 +1,3 @@ - - - + + + diff --git a/packages/nextjs/components/scaffold-eth/FaucetButton.tsx b/packages/nextjs/components/scaffold-eth/FaucetButton.tsx index 440b70b..57a1c0e 100644 --- a/packages/nextjs/components/scaffold-eth/FaucetButton.tsx +++ b/packages/nextjs/components/scaffold-eth/FaucetButton.tsx @@ -1,73 +1,73 @@ -"use client"; - -import { useState } from "react"; -import { createWalletClient, http, parseEther } from "viem"; -import { hardhat } from "viem/chains"; -import { useAccount } from "wagmi"; -import { BanknotesIcon } from "@heroicons/react/24/outline"; -import { useTransactor } from "~~/hooks/scaffold-eth"; -import { useWatchBalance } from "~~/hooks/scaffold-eth/useWatchBalance"; - -// Number of ETH faucet sends to an address -const NUM_OF_ETH = "1"; -const FAUCET_ADDRESS = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; - -const localWalletClient = createWalletClient({ - chain: hardhat, - transport: http(), -}); - -/** - * FaucetButton button which lets you grab eth. - */ -export const FaucetButton = () => { - const { address, chain: ConnectedChain } = useAccount(); - - const { data: balance } = useWatchBalance({ address }); - - const [loading, setLoading] = useState(false); - - const faucetTxn = useTransactor(localWalletClient); - - const sendETH = async () => { - if (!address) return; - try { - setLoading(true); - await faucetTxn({ - account: FAUCET_ADDRESS, - to: address, - value: parseEther(NUM_OF_ETH), - }); - setLoading(false); - } catch (error) { - console.error("⚡️ ~ file: FaucetButton.tsx:sendETH ~ error", error); - setLoading(false); - } - }; - - // Render only on local chain - if (ConnectedChain?.id !== hardhat.id) { - return null; - } - - const isBalanceZero = balance && balance.value === 0n; - - return ( -
    - -
    - ); -}; +"use client"; + +import { useState } from "react"; +import { createWalletClient, http, parseEther } from "viem"; +import { hardhat } from "viem/chains"; +import { useAccount } from "wagmi"; +import { BanknotesIcon } from "@heroicons/react/24/outline"; +import { useTransactor } from "~~/hooks/scaffold-eth"; +import { useWatchBalance } from "~~/hooks/scaffold-eth/useWatchBalance"; + +// Number of ETH faucet sends to an address +const NUM_OF_ETH = "1"; +const FAUCET_ADDRESS = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; + +const localWalletClient = createWalletClient({ + chain: hardhat, + transport: http(), +}); + +/** + * FaucetButton button which lets you grab eth. + */ +export const FaucetButton = () => { + const { address, chain: ConnectedChain } = useAccount(); + + const { data: balance } = useWatchBalance({ address }); + + const [loading, setLoading] = useState(false); + + const faucetTxn = useTransactor(localWalletClient); + + const sendETH = async () => { + if (!address) return; + try { + setLoading(true); + await faucetTxn({ + account: FAUCET_ADDRESS, + to: address, + value: parseEther(NUM_OF_ETH), + }); + setLoading(false); + } catch (error) { + console.error("⚡️ ~ file: FaucetButton.tsx:sendETH ~ error", error); + setLoading(false); + } + }; + + // Render only on local chain + if (ConnectedChain?.id !== hardhat.id) { + return null; + } + + const isBalanceZero = balance && balance.value === 0n; + + return ( +
    + +
    + ); +}; diff --git a/packages/nextjs/styles/App.css b/packages/nextjs/styles/App.css index 5f0f1f5..6bc8181 100644 --- a/packages/nextjs/styles/App.css +++ b/packages/nextjs/styles/App.css @@ -1,114 +1,114 @@ -body, html, #root { - height: 100%; - margin: 0; - font-family: 'Courier New', Courier, monospace; - } - - .app { - display: flex; - flex-direction: column; - height: 100%; - background-size: cover; - background-color: black; - } - - .navbar { - height: 12%; - display: flex; - align-items: center; - padding: 0 20px; - } - - .navbar-logo { - height: 150%; - margin-right: 20px; - } - - .navbar-text { - display: flex; - gap: 40px; - font-size: 1.5rem; - color: white; - cursor: pointer; - } - - .navbar-text .active { - text-decoration: underline; - } - - .main-content { - height: 80%; - display: flex; - padding: 0 20px; - } - - .blank-space { - height: 8%; - } - - .auction-container { - display: flex; - width: 100%; - } - - .auction-column { - width: 27%; - display: flex; - flex-direction: column; - justify-content: space-between; - } - - .auction-middle { - width: 46%; - border: 2px dashed #E91E63; - display: flex; - flex-direction: column; - justify-content: space-between; - padding: 10px; - } - - .button { - background-color: white; - color: black; - padding: 10px 20px; - text-align: center; - cursor: pointer; - margin-bottom: 10px; - } - - .bid-button { - display: flex; - justify-content: space-between; - } - - .bid-button div { - width: 65%; - padding: 10px; - border-right: 1px solid black; - text-align: center; - } - - .track-list, .bids-list { - flex-grow: 1; - display: flex; - flex-direction: column; - justify-content: center; - } - - .track-item, .bid-item { - margin: 5px 0; - } - - .bids-header { - text-align: right; - font-weight: bold; - } - - .end-auction { - background-color: white; - color: black; - padding: 10px 20px; - text-align: center; - cursor: pointer; - } +body, html, #root { + height: 100%; + margin: 0; + font-family: 'Courier New', Courier, monospace; + } + + .app { + display: flex; + flex-direction: column; + height: 100%; + background-size: cover; + background-color: black; + } + + .navbar { + height: 12%; + display: flex; + align-items: center; + padding: 0 20px; + } + + .navbar-logo { + height: 150%; + margin-right: 20px; + } + + .navbar-text { + display: flex; + gap: 40px; + font-size: 1.5rem; + color: white; + cursor: pointer; + } + + .navbar-text .active { + text-decoration: underline; + } + + .main-content { + height: 80%; + display: flex; + padding: 0 20px; + } + + .blank-space { + height: 8%; + } + + .auction-container { + display: flex; + width: 100%; + } + + .auction-column { + width: 27%; + display: flex; + flex-direction: column; + justify-content: space-between; + } + + .auction-middle { + width: 46%; + border: 2px dashed #E91E63; + display: flex; + flex-direction: column; + justify-content: space-between; + padding: 10px; + } + + .button { + background-color: white; + color: black; + padding: 10px 20px; + text-align: center; + cursor: pointer; + margin-bottom: 10px; + } + + .bid-button { + display: flex; + justify-content: space-between; + } + + .bid-button div { + width: 65%; + padding: 10px; + border-right: 1px solid black; + text-align: center; + } + + .track-list, .bids-list { + flex-grow: 1; + display: flex; + flex-direction: column; + justify-content: center; + } + + .track-item, .bid-item { + margin: 5px 0; + } + + .bids-header { + text-align: right; + font-weight: bold; + } + + .end-auction { + background-color: white; + color: black; + padding: 10px 20px; + text-align: center; + cursor: pointer; + } \ No newline at end of file diff --git a/packages/nextjs/styles/AuctionView.css b/packages/nextjs/styles/AuctionView.css index f37639e..bd5c102 100644 --- a/packages/nextjs/styles/AuctionView.css +++ b/packages/nextjs/styles/AuctionView.css @@ -1,67 +1,67 @@ -.auction-container { - display: flex; - width: 100%; - height: 100%; - } - - .auction-column { - width: 27%; - display: flex; - flex-direction: column; - justify-content: space-between; - } - - .auction-middle { - width: 46%; - border: 2px dashed #E91E63; - display: flex; - flex-direction: column; - justify-content: space-between; - padding: 10px; - } - - .button { - background-color: white; - color: black; - padding: 10px 20px; - text-align: center; - cursor: pointer; - margin-bottom: 10px; - } - - .bid-button { - display: flex; - justify-content: space-between; - } - - .bid-button div { - width: 65%; - padding: 10px; - border-right: 1px solid black; - text-align: center; - } - - .track-list, .bids-list { - flex-grow: 1; - display: flex; - flex-direction: column; - justify-content: center; - } - - .track-item, .bid-item { - margin: 5px 0; - } - - .bids-header { - text-align: right; - font-weight: bold; - } - - .end-auction { - background-color: white; - color: black; - padding: 10px 20px; - text-align: center; - cursor: pointer; - } +.auction-container { + display: flex; + width: 100%; + height: 100%; + } + + .auction-column { + width: 27%; + display: flex; + flex-direction: column; + justify-content: space-between; + } + + .auction-middle { + width: 46%; + border: 2px dashed #E91E63; + display: flex; + flex-direction: column; + justify-content: space-between; + padding: 10px; + } + + .button { + background-color: white; + color: black; + padding: 10px 20px; + text-align: center; + cursor: pointer; + margin-bottom: 10px; + } + + .bid-button { + display: flex; + justify-content: space-between; + } + + .bid-button div { + width: 65%; + padding: 10px; + border-right: 1px solid black; + text-align: center; + } + + .track-list, .bids-list { + flex-grow: 1; + display: flex; + flex-direction: column; + justify-content: center; + } + + .track-item, .bid-item { + margin: 5px 0; + } + + .bids-header { + text-align: right; + font-weight: bold; + } + + .end-auction { + background-color: white; + color: black; + padding: 10px 20px; + text-align: center; + cursor: pointer; + } \ No newline at end of file diff --git a/whistle/README.md b/whistle/README.md index fe4820b..fc603ba 100644 --- a/whistle/README.md +++ b/whistle/README.md @@ -1,76 +1,76 @@ - -whistle cli -=========== - -This is a steganography tool for musical carrier waves; a quick hack @ ethBerlin4. - - -build ------ - - $ gcc -O aes.c sha256.c rnd.c whistle.c -o whistle - -or maybe just: - - $ make all - - -use ---- - - $ whistle encrypt message.dat input.wav output.wav - $ whistle decrypt input.wav - - -what happens under the hood ---------------------------- - -Your message is encoded in the lowest bits of the first channel of a 16 bit -(CD quality) `.wav` sound file, which is normally white noise (and after the -encoding, it indeed will be white noise, that one bit of information, around --90 dB, completely destroyed). - -The message is placed at a random location starting somewhere in the first 15 -seconds or so. The encoded message consists of: - -- a handshake pattern (128 random bits) -- a blinded AES key (another 128 bits of randomly looking data) -- a random initialiation vector (yet another 128 random bits) -- the augmented message encrypted with AES128 with the above (unblinded) key + IV - -The augmented message consists of: - -- metadata, containing the message length and the original file name -- and finally the actual message - -To be able even detect that there is a message hidden in a given `.wav` file, -the adversary needs to know the 128 bit handshake pattern; then to actually -decode it, they also need the another 128 bit of blinding key, which unblinds -the actual AES decoding key. These two keys are concatenated into a single -decrypting key. - -Since all the low bits in the resulting file are statistically totally random -(in fact, after the encoding, they are forcibly randomized), this is all -plausibly deniable. - - -third-party library credits ---------------------------- - -- AES code is by "kokke", and is public domain ("unlicense"): https://github.com/kokke/tiny-AES-c -- SHA256 code is by Brad Conte and also public domain: https://github.com/B-Con/crypto-algorithms - - -TODO ----- - -- [x] add a makefile -- [x] make it possible to specify the output file name -- [ ] make a checksum or HMAC or something, for the unlikely case when the decryption - key is wrong but the pattern key is right; then it should say bad decryption key - instead of a segfault crash -- [ ] add an error-correcting code to the message (would be more important with - a more robust message encoding) -- [ ] add a more robust encoding option which survives mp3 etc encoding -- [ ] ... - + +whistle cli +=========== + +This is a steganography tool for musical carrier waves; a quick hack @ ethBerlin4. + + +build +----- + + $ gcc -O aes.c sha256.c rnd.c whistle.c -o whistle + +or maybe just: + + $ make all + + +use +--- + + $ whistle encrypt message.dat input.wav output.wav + $ whistle decrypt input.wav + + +what happens under the hood +--------------------------- + +Your message is encoded in the lowest bits of the first channel of a 16 bit +(CD quality) `.wav` sound file, which is normally white noise (and after the +encoding, it indeed will be white noise, that one bit of information, around +-90 dB, completely destroyed). + +The message is placed at a random location starting somewhere in the first 15 +seconds or so. The encoded message consists of: + +- a handshake pattern (128 random bits) +- a blinded AES key (another 128 bits of randomly looking data) +- a random initialiation vector (yet another 128 random bits) +- the augmented message encrypted with AES128 with the above (unblinded) key + IV + +The augmented message consists of: + +- metadata, containing the message length and the original file name +- and finally the actual message + +To be able even detect that there is a message hidden in a given `.wav` file, +the adversary needs to know the 128 bit handshake pattern; then to actually +decode it, they also need the another 128 bit of blinding key, which unblinds +the actual AES decoding key. These two keys are concatenated into a single +decrypting key. + +Since all the low bits in the resulting file are statistically totally random +(in fact, after the encoding, they are forcibly randomized), this is all +plausibly deniable. + + +third-party library credits +--------------------------- + +- AES code is by "kokke", and is public domain ("unlicense"): https://github.com/kokke/tiny-AES-c +- SHA256 code is by Brad Conte and also public domain: https://github.com/B-Con/crypto-algorithms + + +TODO +---- + +- [x] add a makefile +- [x] make it possible to specify the output file name +- [ ] make a checksum or HMAC or something, for the unlikely case when the decryption + key is wrong but the pattern key is right; then it should say bad decryption key + instead of a segfault crash +- [ ] add an error-correcting code to the message (would be more important with + a more robust message encoding) +- [ ] add a more robust encoding option which survives mp3 etc encoding +- [ ] ... +