import code

This commit is contained in:
zhl 2021-12-07 15:36:30 +08:00
commit 360251d02d
75 changed files with 36394 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/node_modules
/build/contracts
.env
truffle-config.js

44
README.md Normal file
View File

@ -0,0 +1,44 @@
# Crypto Birdies
This project is a clone of the famous Crypto Kitties.
It demonstrates use of the following technologies:
* HTML5
* CSS3
* JavaScript
* Bootstrap
* jQuery
* Solidity
* web3.js
* Truffle
* Ganache
* Mocha.js
* Chai.js
* MetaMask
UI Functionality:
* creation of bird with a 17-digit DNA sequence
* 7 exciting animations for the birds
* millions of color combinations for each bird
* breeding of baby birds
* buying and selling of birds for test ETH
* catalog to display all birds of the user
* market place displaying all active offers of birds both of the current user and other users
Technical Functionality:
* Creation and management of ERC721 tokens
* Payments with ERC20 tokens (testnet)
* Compliance with IERC721 and IERC165 (Open Zeppelin)
* 95 unit tests for the smart contract code utilizing three additional test contracts
* Implementation of pause functionality to allow for maintenance by the contract owner
* Full SafeMath implementation for full protection against Over- and Underflow
* Checks / Effects / Interactions logic to prevent re-entrency attacks
* No external library calls to prevent Parity Freeze szenario
* Independent Market Contract handling the trading of the NFT tokens
* Truffle migrations
-------------------------------------------------------------------------------------------------
* Live demonstration: https://cryptobirdies.netlify.app
* Birdcontract: https://ropsten.etherscan.io/address/0x70e2324ccf7a76e201dff26d4749ed1bb821c305
* Marketcontract: https://ropsten.etherscan.io/address/0x78ad2f9c3924278692125a23ed05d4e5facfd97c

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,331 @@
/*!
* Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
* Copyright 2011-2019 The Bootstrap Authors
* Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
font-family: sans-serif;
line-height: 1.15;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
display: block;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
text-align: left;
background-color: #fff;
}
[tabindex="-1"]:focus {
outline: 0 !important;
}
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: 0.5rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-original-title] {
text-decoration: underline;
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
border-bottom: 0;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: .5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 80%;
}
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -.25em;
}
sup {
top: -.5em;
}
a {
color: #007bff;
text-decoration: none;
background-color: transparent;
}
a:hover {
color: #0056b3;
text-decoration: underline;
}
a:not([href]):not([tabindex]) {
color: inherit;
text-decoration: none;
}
a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {
color: inherit;
text-decoration: none;
}
a:not([href]):not([tabindex]):focus {
outline: 0;
}
pre,
code,
kbd,
samp {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 1em;
}
pre {
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
}
figure {
margin: 0 0 1rem;
}
img {
vertical-align: middle;
border-style: none;
}
svg {
overflow: hidden;
vertical-align: middle;
}
table {
border-collapse: collapse;
}
caption {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
color: #6c757d;
text-align: left;
caption-side: bottom;
}
th {
text-align: inherit;
}
label {
display: inline-block;
margin-bottom: 0.5rem;
}
button {
border-radius: 0;
}
button:focus {
outline: 1px dotted;
outline: 5px auto -webkit-focus-ring-color;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
select {
word-wrap: normal;
}
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
button:not(:disabled),
[type="button"]:not(:disabled),
[type="reset"]:not(:disabled),
[type="submit"]:not(:disabled) {
cursor: pointer;
}
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
padding: 0;
border-style: none;
}
input[type="radio"],
input[type="checkbox"] {
box-sizing: border-box;
padding: 0;
}
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"] {
-webkit-appearance: listbox;
}
textarea {
overflow: auto;
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
display: block;
width: 100%;
max-width: 100%;
padding: 0;
margin-bottom: .5rem;
font-size: 1.5rem;
line-height: inherit;
color: inherit;
white-space: normal;
}
progress {
vertical-align: baseline;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
outline-offset: -2px;
-webkit-appearance: none;
}
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
summary {
display: list-item;
cursor: pointer;
}
template {
display: none;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
/*!
* Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
* Copyright 2011-2019 The Bootstrap Authors
* Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.min.css.map */

File diff suppressed because one or more lines are too long

10038
client/assets/bootstrap/css/bootstrap.css vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4435
client/assets/bootstrap/js/bootstrap.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,142 @@
.slowRotateBird {
animation: rotateBird 1s infinite;
}
@keyframes rotateBird {
0% {
transform: rotate(0deg);
}
30% {
transform: rotate(5deg);
}
60% {
transform: rotate(-5deg);
}
100% {
transform: rotate(0deg);
}
}
.floatingBird {
animation: floatBird 3s ease-out infinite;
}
@keyframes floatBird {
50% {
transform: translate(0, -20px);
}
}
.compressingBird {
animation: compressBird 3s infinite;
}
@keyframes compressBird {
0% {
transform: scaleY(0);
}
30% {
transform: scaleY(1.3);
}
60% {
transform: scaleY(1);
}
100% {
transform: scaleY(0);
}
}
.upperSpeakingBird {
animation: upperSpeakBird 1s infinite;
}
@keyframes upperSpeakBird {
50% {
transform: rotate(-90deg) skewY(20deg) scale(1.5, 2.7);
}
}
.lowerSpeakingBird {
animation: lowerSpeakBird 1s infinite;
}
@keyframes lowerSpeakBird {
50% {
transform: rotate(135deg) skewY(20deg) scale(1.5, 1.5) translateX(-0.9em) translateY(-0.5em);
top: 23em;
left: 28em;
}
}
.topWaggingTail {
animation: topWagTail 1s infinite;
}
@keyframes topWagTail {
50% {
transform: rotate(60deg);
}
}
.middleWaggingTail {
animation: middleWagTail 1s infinite;
}
@keyframes middleWagTail {
50% {
transform: rotate(20deg) scale(1.1);
}
}
.bottomWaggingTail {
animation: bottomWagTail 1s infinite;
}
@keyframes bottomWagTail {
50% {
transform: rotate(-50deg);
}
}
.topAttention {
animation: tAttention 6s infinite;
}
@keyframes tAttention {
90% {
transform: rotate(60deg);
}
}
.bottomAttention {
animation: bAttention 6s infinite;
}
@keyframes bAttention {
90% {
transform: rotate(50deg);
}
}
.evolvingHeart {
animation: evolveHeart 6s infinite;
}
@keyframes evolveHeart {
0% {
transform: scale(0);
}
50% {
transform: scale(0.5);
}
100% {
transform: scale(0);
}
}

240
client/assets/css/bird.css Normal file
View File

@ -0,0 +1,240 @@
.bird {
left:10em;
font-size: 5px;
position:relative;
top: 15em;
}
.feather_top {
background: #ce000f;
border: 0.8em solid black;
border-radius: 100% 100% 100% 100% / 80% 100% 80% 100% ;
border-right:0;
height: 6em;
left: 16em;
position: absolute;
top: -6em;
transform: rotate(40deg);
width: 17em;
z-index: 6;
}
.feather_bottom {
background: #ce000f;
border: 0.8em solid black;
border-radius: 100% 100% 100% 100% / 80% 90% 50% 100% ;
border-right: 0;
height: 5em;
left: 8em;
position: absolute;
top: -4em;
transform: rotate(10deg);
width: 15em;
z-index: 6;
}
.bird_body {
border: 1em solid black;
border-radius: 100% / 120% 100% 95% 85%;
height: 42em;
position:absolute;
width: 45em;
z-index: 5;
}
.bird_body_inner {
background: #ce000f;
border: none;
height: 40.2em;
position:absolute;
width: 43em;
z-index: 3
}
.deco_1 {
background: #ab060c;
border: none;
border-radius: 100% / 120% 100% 95% 85%;
top: 24em;
height: 4.5em;
left: 7em;
position: absolute;
transform: rotate(-25deg);
width: 4em;
z-index: 4;
}
.deco_2 {
background: #ab060c;
border: none;
border-radius: 100% / 120% 100% 95% 85%;
top: 20em;
height: 7.5em;
left: 12em;
position: absolute;
transform: rotate(-15deg);
width: 4em;
z-index: 4;
}
.deco_3 {
background: #ab060c;
border: none;
border-radius: 100% / 120% 100% 95% 85%;
top: 19em;
height: 9em;
left: 17em;
position: absolute;
transform: rotate(-10deg);
width: 10em;
z-index: 4;
}
.deco_4 {
background: #ab060c;
border: none;
border-radius: 100% / 120% 100% 95% 85%;
top: 17.5em;
height: 9em;
left: 31em;
position: absolute;
transform: rotate(-10deg);
width: 10em;
z-index: 40;
}
.belly {
border: #E5E8D5 solid;
border-bottom-width: 0;
border-left-width: 14em;
border-radius: 100% 100% 100% 100% / 120% 120% 80% 80%;
border-right-width: 14em;
border-top-width: 12em;
left: 8.5em;
position: absolute;
top: 29em;
z-index: 5
}
.face {
position: relative;
}
.eye {
background: #dddddd;
border: 0.9em black solid;
border-radius: 100%;
height: 10.7em;
position: absolute;
width: 10.7em;
z-index: 6;
}
.pupil {
background: black;
border-radius: 100%;
height: 3em;
position: relative;
width: 3em;
z-index: 10;
}
.eye_right {
left: 30em;
top: 16em;
}
.eye_left {
left: 20em;
top: 16em;
}
.eye_right .pupil {
left: 1.5em;
top: 3em;
}
.eye_left .pupil {
left: 5em;
top: 3em;
}
.eyebrow {
background: black;
height: 3.2em;
position: absolute;
width: 13em;
z-index: 7;
}
.eye_right .eyebrow {
left: -1em;
top: -1.5em;
transform: rotate(-11deg);
}
.eye_left .eyebrow {
left: -3em;
top: -1.5em;
transform: rotate(11deg);
}
.beak_upper {
background: #e9b90d;
border: 0.3em solid black;
border-bottom-left-radius: 200%;
border-top-left-radius: 10%;
border-top-right-radius: 40%;
height: 5em;
left: 31em;
position: relative;
top: 26em;
transform: rotate(-70deg) skewY(20deg) scale(1.5, 2.7);
width: 5em;
z-index: 10;
}
.beak_lower {
background: #e28810;
border: 0.3em solid black;
border-bottom-left-radius: 200%;
border-top-left-radius: 10%;
border-top-right-radius: 30%;
height: 7.5em;
left: 30em;
position: relative;
top: 20em;
transform: rotate(120deg) skewY(20deg) scale(1.5, 1.5);
width: 6em;
z-index: 5;
}
.tail_top {
border-color: transparent transparent transparent black;
border-style: solid;
position: absolute;
border-width: 2em 0em 2em 10em;
left: -5em;
top: 16.5em;
transform: rotate(45deg);
}
.tail_middle {
border-color: transparent transparent transparent black;
border-style: solid;
position: absolute;
border-width: 3em 0em 2em 15em;
left: -8em;
top: 18em;
transform: rotate(12deg);
}
.tail_bottom {
border-color: transparent transparent transparent black;
border-style: solid;
position: absolute;
border-width: 2em 0em 1em 7em;
left: -4em;
top: 21.2em;
transform: rotate(-35deg);
}

View File

@ -0,0 +1,306 @@
/* HTML Elements */
body {
background:
url(../images/vector-river-scene-with-trees-and-hills.jpg);
background-size: cover;
font-family: Poppins;
font-weight: 500;
letter-spacing: 1px;
}
footer {
background: whitesmoke;
border-radius: 5px;
height: 30px;
padding: 2vh;
padding-bottom: 40px;
text-align: center;
width: auto;
}
h1 {
color: #f8f9fa;
}
html {
box-sizing: border-box;
color: rgb(48, 46, 46);overflow-y: scroll;
}
p {
color: #f8f9fa;
height: 0.8em;
}
/* Classes */
.birdAttributes {
background-color: #ededed;
border-radius: 10px;
left: 3em;
padding: 25px;
}
.birdBox {
background-color: #f8f9fa;
border-radius: 10px;
padding-bottom: 10px;
padding-left: 30px;
padding-right: 30px;
z-index: 20;
}
.bottomList {
margin-left: -2.5em;
}
.buyBox {
background-color: #f8f9fa;
border-radius: 10px;
display: inline-flex;
height: 34em;
min-width: 20.7em;
max-width: 20.7em;
z-index: 20;
}
.buyButton {
border-radius: 5px;
margin-left: 7em;
}
.cancelButton {
border-radius: 5px;
margin-left: 5em;
}
.card-deck{
background: transparent;
border-width: 5px;
position: relative;
top: 0em;
z-index: 1;
}
.card-img-top {
height: 200px;
}
.card-special {
background-color: seagreen;
height: 10em;
}
.card-text {
color: black;
font-weight: bold;
text-align: center;
}
.card-title {
font-weight: bold;
text-align: center;
}
.catalogBox {
background-color: #f8f9fa;
border-radius: 10px;
height: 34em;
min-width: 20.7em;
max-width: 20.7em;
padding-right: 30px;
z-index: 20;
}
.dnaDiv {
bottom: 5px;
font-size: 18px;
left:20px;
position: absolute;
}
.evolvingHeart {
left: -20em;
position: relative;
top: -20em;
}
.navbar {
border-radius: 5px;
color: black;
font-weight: bold;
}
.offerBox {
background-color: #f8f9fa;
border-radius: 10px;
display: inline-flex;
height: 34em;
min-width: 20.7em;
max-width: 20.7em;
z-index: 20;
}
.row {
margin-left: -0.4em;
}
.submitButton {
margin-right: 1em;
}
.topCard {
background: seagreen;
border-width: 5px;
float: none;
margin: 0 auto;
margin-bottom: 10px;
position: relative;
z-index: 1;
}
/* IDs */
#breedAgainButton {
left: 28.4em;
position: relative;
top: -65em;
}
#breedButton {
left: 10em;
position: relative;
top: -50em;
}
#breedFooter {
position: relative;
top: -33em;
}
#cardButton {
left: 2em;
position: relative;
}
#cardTitle {
color: #343a40;
text-align: center;
}
#childBox {
background-color: #f8f9fa;
border-radius: 10px;
height: 31em;
min-width: 21em;
max-width: 21em;
padding-right: 30px;
z-index: 20;
}
#childDisplay {
left: 21.3em;
opacity: 90%;
position: relative;
top: -66em;
width: 30em;
z-index: 50;
}
#createButton {
border-radius: 5px;
left: 21em;
}
#dadData {
float: right;
margin-right: 1em;
}
#dameBox {
background-color: #fdb1f3;
border-radius: 10px;
height: 31em;
min-width: 21em;
max-width: 21em;
padding-right: 30px;
z-index: 20;
}
#dameButton {
left: 8em;
position: relative;
top: -34em;
}
#dameDisplay {
left: 1em;
opacity: 90%;
position: relative;
top: -3em;
width: 30em;
}
#defaultButton {
border-radius: 5px;
left: 3.4em;
}
#genData {
float: right;
margin-right: 1em;
}
#idData {
float: left;
}
#logo {
border-radius: 40%;
}
#mumData {
float: left;
}
#offerAmount {
position: relative;
width: min-content;
}
#pauseMessage {
text-align: center;
}
#randomizeButton {
border-radius: 5px;
left: 0.2em;
}
#sireBox {
background-color: #5caaf8;
border-radius: 10px;
height: 31em;
min-width: 21em;
max-width: 21em;
padding-right: 30px;
z-index: 20;
}
#sireButton {
left: 40em;
position: relative;
top: -34em;
}
#sireDisplay {
left: 41.5em;
opacity: 90%;
position: relative;
top: -34.5em;
width: 30em;
}
#swapButton {
left: 26.4em;
position: relative;
top: -49em;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 884 KiB

BIN
client/assets/js/.DS_Store vendored Normal file

Binary file not shown.

875
client/assets/js/abi.js Normal file
View File

@ -0,0 +1,875 @@
var abi = {
birdContract: [
{
"inputs": [
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "symbol",
"type": "string"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "approved",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"indexed": false,
"internalType": "bool",
"name": "approved",
"type": "bool"
}
],
"name": "ApprovalForAll",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "birdId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "mumId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "dadId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "genes",
"type": "uint256"
}
],
"name": "Birth",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"constant": true,
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "approvalOneBird",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "birdOwner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "close",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "gen0Counter",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "maxGen0Birds",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getContractOwner",
"outputs": [
{
"internalType": "address",
"name": "contractowner",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "uint256",
"name": "_dadId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_mumId",
"type": "uint256"
}
],
"name": "breed",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"internalType": "bytes4",
"name": "_interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "uint256",
"name": "genes",
"type": "uint256"
}
],
"name": "createBirdGen0",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getBird",
"outputs": [
{
"internalType": "uint256",
"name": "genes",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "birthTime",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "mumId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "dadId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "generation",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "getAllBirdsOfOwner",
"outputs": [
{
"internalType": "uint256[]",
"name": "",
"type": "uint256[]"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "balance",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "total",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "tokenName",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "tokenSymbol",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "ownerOf",
"outputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "address",
"name": "_approved",
"type": "address"
},
{
"internalType": "uint256",
"name": "_tokenId",
"type": "uint256"
}
],
"name": "approve",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "address",
"name": "_operator",
"type": "address"
},
{
"internalType": "bool",
"name": "_approved",
"type": "bool"
}
],
"name": "setApprovalForAll",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"internalType": "uint256",
"name": "_tokenId",
"type": "uint256"
}
],
"name": "getApproved",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"internalType": "address",
"name": "_owner",
"type": "address"
},
{
"internalType": "address",
"name": "_operator",
"type": "address"
}
],
"name": "isApprovedForAll",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "address",
"name": "_from",
"type": "address"
},
{
"internalType": "address",
"name": "_to",
"type": "address"
},
{
"internalType": "uint256",
"name": "_tokenId",
"type": "uint256"
}
],
"name": "safeTransferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "address",
"name": "_from",
"type": "address"
},
{
"internalType": "address",
"name": "_to",
"type": "address"
},
{
"internalType": "uint256",
"name": "_tokenId",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"name": "safeTransferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "address",
"name": "_from",
"type": "address"
},
{
"internalType": "address",
"name": "_to",
"type": "address"
},
{
"internalType": "uint256",
"name": "_tokenId",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}
],
marketContract: [
{
"inputs": [
{
"internalType": "address",
"name": "_contractAddress",
"type": "address"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "TxType",
"type": "string"
},
{
"indexed": false,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "MarketTransaction",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "message",
"type": "string"
},
{
"indexed": false,
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "MonetaryTransaction",
"type": "event"
},
{
"constant": false,
"inputs": [
{
"internalType": "address",
"name": "_contractAddress",
"type": "address"
}
],
"name": "setContract",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "pause",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "resume",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "isPaused",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"internalType": "uint256",
"name": "_tokenId",
"type": "uint256"
}
],
"name": "getOffer",
"outputs": [
{
"internalType": "address",
"name": "seller",
"type": "address"
},
{
"internalType": "uint256",
"name": "price",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "index",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "bool",
"name": "active",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getAllTokensOnSale",
"outputs": [
{
"internalType": "uint256[]",
"name": "listOfOffers",
"type": "uint256[]"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "uint256",
"name": "_price",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_tokenId",
"type": "uint256"
}
],
"name": "setOffer",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "uint256",
"name": "_tokenId",
"type": "uint256"
}
],
"name": "removeOffer",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "uint256",
"name": "_tokenId",
"type": "uint256"
}
],
"name": "buyBird",
"outputs": [],
"payable": true,
"stateMutability": "payable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getBalance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "withdrawFunds",
"outputs": [],
"payable": true,
"stateMutability": "payable",
"type": "function"
}
]
}

View File

@ -0,0 +1,369 @@
// var web3 = new Web3(Web3.givenProvider);//Wallet will inject the selected network
var web3 = new Web3('ws://192.168.100.22:8545')
// var web3 = new Web3('ws://localhost:7545')
ethereum.autoRefreshOnNetworkChange = false;
var birdInstance;
var marketInstance;
var user;
var access = false;
// localhost
// var birdAddress = "0xfB0fA5Ae35E9A2d079EDd2Eb9D627aa2f61E81CE";
// var marketAddress = "0x827953AE5656E0f922fa898f57B2eE600BFE4b8F"
// 192.168.100.22
var birdAddress = "0xCfEB869F69431e42cdB54A4F4f105C19C080A601";
var marketAddress = "0xC89Ce4735882C9F0f0FE26686c53074E09B0D550"
// var birdAddress = "0x70e2324ccf7a76e201dff26d4749ed1bb821c305"; //Ropsten: 0x70e2324ccf7a76e201dff26d4749ed1bb821c305
// var marketAddress = "0x78ad2f9c3924278692125a23ed05d4e5facfd97c"; // Ropsten: 0x78ad2f9c3924278692125a23ed05d4e5facfd97c
async function connectWallet() {
return window.ethereum.enable().then(function(accounts){
user = accounts[0];
birdInstance = new web3.eth.Contract(abi.birdContract, birdAddress, {from: user});
marketInstance = new web3.eth.Contract(abi.marketContract, marketAddress, {from: user});
birdInstance.events.Birth()
.on('data', async function (event) {
let owner = event.returnValues.owner;
let birdId = event.returnValues.birdId;
let mumId = event.returnValues.mumId;
let dadId = event.returnValues.dadId;
let genes = event.returnValues.genes;
//check if the event belongs to one of the currently connected addresses
access = await isCurrentUserOwner(owner);
//birth events
if (location.href.includes("breeding") && (access)) {
$('#birdCreation').text(
"A new bird is born! Your baby bird will appear in the catalog after confirmation from the blockchain. Owner: "
+ owner
+ " | BirdID: " + birdId
+ " | MumID: " + mumId
+ " | DadID: " + dadId
+ " | Genes: " + genes);
await renderChild(birdId);
$('#breedAgainButton').css("display", "block");
$('#breedFooter').css("top", "-65.5em");
$('#breedAgainButton').on("click", () => {
location.reload();
});
} else if (location.href.includes("studio") && (access)) {
$('#birdCreation').css("display", "block");
$('#birdCreation').text(
"Bird successfully created! After confirmation from the blockchain, your new bird will appear in the catalog. Owner: "
+ owner
+ " | BirdID: " + birdId
+ " | MumID: " + mumId
+ " | DadID: " + dadId
+ " | Genes: " + genes);
};
})
.on('error', console.error);
marketInstance.events.MarketTransaction()
.on('data', async function (event) {
let eventType = event.returnValues.TxType;
let owner = event.returnValues.owner;
let tokenId = event.returnValues.tokenId;
//check if the event belongs to one of the currently connected addresses
access = await isCurrentUserOwner(owner);
//events
if ((eventType == "Offer created") && (access)) {
$('#offerCreated').css("display", "block");
$('#offerCreated').text(
"Offer successfully created! After confirmation from the blockchain, your new offer will appear in the market place. Owner: "
+ owner + " | BirdID: " + tokenId);
};
if ((eventType == "Offer removed") && (access)) {
$('#offerRemoved').css("display", "block");
$('#offerRemoved').text(
"Offer successfully removed! After confirmation from the blockchain, your bird will again appear in the catalog. Owner: "
+ user + " | BirdID: " + tokenId);
};
if ((eventType == "Bird successfully purchased") && (access)) {
$('#birdPurchased').css("display", "block");
$('#birdPurchased').text(
"Bird successfully purchased! After confirmation from the blockchain, your new bird will appear in the catalog. Owner: "
+ user + " | BirdID: " + tokenId);
};
})
.on('error', console.error);
});
};
async function isCurrentUserOwner(eventOwner) {
var currentUsers = await web3.eth.getAccounts();
for (let i = 0; i < currentUsers.length; i++) {
if (currentUsers[i] == eventOwner) {
return true;
} else {
return false;
};
};
};
async function checkPause() {
return await marketInstance.methods.isPaused().call();
};
async function pauseResumeContract() {
$('#pauseMessage').show();
$('#pauseMessage').text("Waiting for confirmations from blockchain...");
if(!await checkPause()){
await marketInstance.methods.pause().send({}, function(error){
if (error) {
console.log(error);
}});
} else {
await marketInstance.methods.resume().send({}, function(error){
if (error) {
console.log(error);
};
});
};
window.location.reload();
};
async function initializeMarketplace() {
var marketplaceApprovedOperator = await birdInstance.methods.isApprovedForAll(
user, marketAddress).call();
if (marketplaceApprovedOperator == false) {
await birdInstance.methods.setApprovalForAll(marketAddress, true).send(
{gas: 1000000}, function(error){
if (error) {
console.log(error);
};
});
};
};
async function onlyOwnerAccess() {//limits access to studio and pause/resume to contract owner
var owner = await birdInstance.methods.getContractOwner().call();
owner = owner.toLowerCase()
if (user == owner) {
$('#designStudio').show();
if(await checkPause()) {
$('#pauseButton').text('Resume Contract');
$('#pauseButton').show();
} else {
$('#pauseButton').text('Pause Contract');
$('#pauseButton').show();
};
$('#pauseButton').show();
//logic for other users
} else {
$('#designStudio').hide();
$('#pauseButton').hide();
if (location.href.replace(location.origin,'') == "/client/studio.html") {
window.location.href = "./index.html";
};
};
// var currentUser = await web3.eth.getAccounts();
// for (let i = 0; i < currentUser.length; i++) {
// //logic for owner
// if (currentUser[i] == owner) {
// $('#designStudio').show();
// if(await checkPause()) {
// $('#pauseButton').text('Resume Contract');
// $('#pauseButton').show();
// } else {
// $('#pauseButton').text('Pause Contract');
// $('#pauseButton').show();
// };
// $('#pauseButton').show();
// //logic for other users
// } else {
// $('#designStudio').hide();
// $('#pauseButton').hide();
// if (location.href.replace(location.origin,'') == "/client/studio.html") {
// window.location.href = "./index.html";
// };
// };
// };
//Pause message applies to all users
if(await checkPause()) {
$('#pauseMessage').show();
$('#withdrawBox').hide();
} else {
$('#pauseMessage').hide();
$('#withdrawBox').show();
};
//event listener for pause button
$('#pauseButton').click(async ()=>{
if(await checkPause()) {
alert('Are you sure you want to RESUME withdrawFunds() and buyBird() for all users?');
} else {
alert('Are you sure you want to PAUSE withdrawFunds() and buyBird() for all users?');
};
await pauseResumeContract();
});
};
async function withdraw() {
await marketInstance.methods.withdrawFunds().send({}, function(error){
if (error) {
$('#withdrawButton').show();
console.log(error);
};
});
};
async function returnBalance() {
var balance;
try {
balance = await marketInstance.methods.getBalance().call();
if (balance >= 0) {
return web3.utils.fromWei(balance);
}
} catch (error) {
console.log(error);
return;
};
};
async function sellBird(price, id) {
$('#offerCreated').css("display", "block");
$('#offerCreated').text("Waiting for confirmations from blockchain...");
var inWei = web3.utils.toWei(price, "ether");
await marketInstance.methods.setOffer(inWei, id).send({gas: 1000000}, function(error){
if (error) {
$(`#birdPrice${id}`).show();
$(`#offerButton${id}`).show();
console.log(error);
};
});
};
async function removeOffer(id) {
$('#offerRemoved').css("display", "block");
$('#offerRemoved').text("Waiting for confirmations from blockchain...");
await marketInstance.methods.removeOffer(id).send({}, function(error){
if (error) {
$(`#cancelButton${id}`).show();
console.log(error);
};
});
};
async function buyBird(price, id) {
$('#birdPurchased').css("display", "block");
$('#birdPurchased').text("Waiting for confirmations from blockchain...");
var inWei = web3.utils.toWei(price, "ether");
await marketInstance.methods.buyBird(id).send({ value: inWei, gas: 1000000 }, function(error){
if (error) {
$(`#buyButton${id}`).show();
console.log(error);
};
});
};
async function getPrice(id) {
var result;
try {
result = await marketInstance.methods.getOffer(id).call();
if (result.price > 0 && result.active == true) {
ethPrice = web3.utils.fromWei(result.price, "ether");
return ethPrice;
}
} catch (error) {
console.log(error);
return;
};
};
async function createBird() {
await birdInstance.methods.createBirdGen0(getDna()).send({gas: 1000000}, function(error){
if (error) {
console.log(error);
};
});
};
async function getBirdsOfOwner() {
var ids = [];
try {
ids = await birdInstance.methods.getAllBirdsOfOwner(user).call();
} catch (error) {
console.log(error);
};
return ids;
};
async function getBirdsOnSale() {
var ids = [];
try {
ids = await marketInstance.methods.getAllTokensOnSale().call();
} catch (error) {
console.log(error);
};
return ids;
};
async function buildCatalog(ids){
for (let i = 0; i < ids.length; i++) {
bird = await birdInstance.methods.getBird(ids[i]).call();
appendBirdToCatalog(bird, ids[i]);
};
activateCatalogEventListeners();//must be activated after all buttons are rendered.
};
async function buildModal(ids){
for (let i = 0; i < ids.length; i++) {
bird = await birdInstance.methods.getBird(ids[i]).call();
appendBirdToModal(bird, ids[i]);
};
};
async function buildMarket(ids){
for (let i = 0; i < ids.length; i++) {
bird = await birdInstance.methods.getBird(ids[i]).call();
await appendBirdToMarket(bird, ids[i]);
};
await activateBuyButtonListeners();//must be activated after all buttons are rendered.
};
async function buildOffers(ids){
for (let i = 0; i < ids.length; i++) {
bird = await birdInstance.methods.getBird(ids[i]).call();
await appendBirdToOffers(bird, ids[i]);
};
activateCancelButtonListeners();
};
async function getBirdDna(id) {
return await birdInstance.methods.getBird(id).call();
};
async function breedBird(dadId, mumId) {
$('#birdCreation').show();
$('#birdCreation').text("Waiting for confirmations from blockchain...");
$('.evolvingHeart').show();
$('#breedButton').hide();
$('#dameButton').hide();
$('#sireButton').hide();
$('#swapButton').hide();
$('#breedFooter').css("top", "-99em");
await birdInstance.methods.breed(dadId, mumId).send({gas: 1000000}, function(error){
if (error) {
$('#birdCreation').hide();
$('.evolvingHeart').hide();
$('#breedButton').show();
$('#dameButton').show();
$('#sireButton').show();
$('#breedFooter').css("top", "-33em");
if(ids.length == 2) {
$('#swapButton').show();
};
console.log(error);
};
});
};

View File

@ -0,0 +1,451 @@
var dameId;
var sireId;
var ids;
$(document).ready(async () => { //when page is loaded, get latest instance of blockchain
$('#breedAgainButton').css("display", "none");
await connectWallet(); //connect MetaMask (if not already connected)
await onlyOwnerAccess();
ids = await getBirdsOfOwner(); //fill array with ids for all birds of this address
dameId = ids[0];
sireId = ids[1];
if (ids.length == 2) { //user must own at least two birds to continue
await renderDameAndSire(dameId, sireId);
$('#insufficient').hide();
$('#swapButton').css("display", "block");
$('#swapButton').click(async function() { //swap dame and sire if only 2 birds in array
var helper = dameId;
dameId = sireId;
sireId = helper;
await renderDameAndSire(dameId, sireId);
})
} else if (ids.length > 2) {
$('#insufficient').hide();
$('#swapButton').css("display", "none");
await buildModal(ids); //iterates through array and returns full info from blockchain
await renderDameAndSire(ids[0], ids[1]);
};
activateMouseListeners();
});
function appendBirdToModal(dna, id) {
modalBox(id);
renderBird(`#BirdBox${id}`, birdDna(dna), id);
};
async function setUpModal() {
$('.row').empty(); //clear modal content
ids = await getBirdsOfOwner(); //get a fresh array from the blockcahin
ids = [...ids]
var index = ids.findIndex(bird => bird == dameId); //search for dame
if (index >= 0) { //make sure element is in array
ids.splice(index, 1); //remove current dame from array
};
index = ids.findIndex(bird => bird == sireId);
if (index >= 0) { //make sure element is in array
ids.splice(index, 1); //remove current sire from array
};
await buildModal(ids); //iterates through array and returns full info from blockchain
$('#birdSelection').modal('show'); //open modal
activateMouseListeners();
};
async function renderDameAndSire(dameId, sireId) {
dameBox(dameId);
var dna = await getBirdDna(dameId);//returns bird instance from blockchain
var obj = birdDna(dna, dameId);//creates dna object for rendering
renderBird(`#dameBox`, obj, dameId);//renders bird
sireBox(sireId);
dna = await getBirdDna(sireId)
obj = birdDna(dna, sireId);
renderBird(`#sireBox`, obj, sireId);
};
async function renderChild(id) {
childBox(id);
var dna = await getBirdDna(id);
var obj = birdDna(dna, id);
renderBird(`#childBox`, obj, id);
};
//Listeners for buttons
$('#dameButton').on("click", async () => {
await setUpModal();
selectDame(); //functionality when dame is to be selected
});
$('#sireButton').on("click", async () => {
await setUpModal();
selectSire();//modal functionality when sire is to be selected
});
$('#breedButton').on("click", async () => { //sends parent IDs to blockchain with request to breed child
await breedBird(sireId, dameId);
});
//Listeners for selections
function selectDame(){
$(`[id^='BirdBox']`).off("click");
$(`[id^='BirdBox']`).on("click", async function() { //arrow function ES6 doesn't work with $(this)
dameId = $(this).attr("id").substring(7); //works after removing arrow function.
dameBox(dameId);//render box
var dna = await getBirdDna(dameId)
var obj = birdDna(dna, dameId);
renderBird(`#dameBox`, obj, dameId);//render bird
$('#birdSelection').modal('toggle'); //close modal
});
};
function selectSire(){
$(`[id^='BirdBox']`).off("click");
$(`[id^='BirdBox']`).on("click", async function() { //arrow function ES6 doesn't work with $(this)
sireId = $(this).attr("id").substring(7); //works after removing arrow function.
sireBox(sireId);//render box
var dna = await getBirdDna(sireId)
var obj = birdDna(dna, sireId);
renderBird(`#sireBox`, obj, sireId);//render bird
$('#birdSelection').modal('toggle'); //close modal
});
};
//Listener for eye animation
function activateMouseListeners() {
$('.CatalogBox').on("mousemove", () => {
var eyeballs = $('.eyesFollow');
document.onmousemove = function(event) {
var x = event.clientX * 65 / window.innerWidth + "%";
var y = event.clientY * 65 / window.innerHeight + "%";
for (let i = 0; i < eyeballs.length; i++) {
eyeballs[i].style.left = x;
eyeballs[i].style.top = y;
};
};
});
};
//dynamic elements for breeding page
function dameBox(id) {
var boxDiv = `<div id="dameBox" class="col-lg-6 CatalogBox m-2 light-b-shadow">
<div class="bird">
<div class="tail">
<div class="tail_top"></div>
<div class="tail_middle"></div>
<div class="tail_bottom"></div>
</div>
<div class="feather">
<div class="feather_top"></div>
<div class="feather_bottom"></div>
</div>
<div class="bird_body">
<div class="bird_body bird_body_inner"></div>
<div class="deco_1"></div>
<div class="deco_2"></div>
<div class="deco_3"></div>
<div class="deco_4"></div>
</div>
<div class="belly"></div>
<div class="face">
<div class="eye eye_right">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="eye eye_left">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="beak">
<div class="beak_upper"></div>
<div class="beak_lower"></div>
</div>
</div>
</div>
<br>
<div class="dnaDiv">
<b>
<div id="idData">
ID:
<span>` + id + `</span>
</div>
<div id="genData">
GEN:
<span id="generation` + id + `"></span>
</div><br>
<div id="mumData">
MUM:
<span id="mum` + id + `"></span>
</div>
<div id="dadData">
DAD:
<span align="right" id="dad` + id + `"></span><br>
</div><br>
DNA:
<span id="dnaTopFeather` + id + `"></span>
<span id="dnaBodyFeather` + id + `"></span>
<span id="dnaTopBeak` + id + `"></span>
<span id="dnaBottomBeak` + id + `"></span>
<span id="dnaEyesShape` + id + `"></span>
<span id="dnaDecorationPattern` + id + `"></span>
<span id="dnaDecorationAtEye` + id + `"></span>
<span id="dnaDecorationMid` + id + `"></span>
<span id="dnaDecorationSmall` + id + `"></span>
<span id="dnaAnimation` + id + `"></span><br>
<ul class="ml-4">
<li class="bottomList"><span id="bottomeyetext`
+ id + `"></span></li>
<li class="bottomList"><span id="bottomdecorationpatterntext`
+ id + `"></span></li>
<li class="bottomList"><span id="bottomanimationtext`
+ id + `"></span></li>
</ul>
<div align="center">DAME</div>
</b>
</div>
</div>`
$('#dameDisplay').empty();
$('#dameDisplay').append(boxDiv);
};
function sireBox(id) {
var boxDiv = `<div id="sireBox" class="col-lg-4 CatalogBox m-2 light-b-shadow">
<div class="bird">
<div class="tail">
<div class="tail_top"></div>
<div class="tail_middle"></div>
<div class="tail_bottom"></div>
</div>
<div class="feather">
<div class="feather_top"></div>
<div class="feather_bottom"></div>
</div>
<div class="bird_body">
<div class="bird_body bird_body_inner"></div>
<div class="deco_1"></div>
<div class="deco_2"></div>
<div class="deco_3"></div>
<div class="deco_4"></div>
</div>
<div class="belly"></div>
<div class="face">
<div class="eye eye_right">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="eye eye_left">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="beak">
<div class="beak_upper"></div>
<div class="beak_lower"></div>
</div>
</div>
</div>
<br>
<div class="dnaDiv">
<b>
<div id="idData">
ID:
<span>` + id + `</span>
</div>
<div id="genData">
GEN:
<span id="generation` + id + `"></span>
</div><br>
<div id="mumData">
MUM:
<span id="mum` + id + `"></span>
</div>
<div id="dadData">
DAD:
<span align="right" id="dad` + id + `"></span><br>
</div><br>
DNA:
<span id="dnaTopFeather` + id + `"></span>
<span id="dnaBodyFeather` + id + `"></span>
<span id="dnaTopBeak` + id + `"></span>
<span id="dnaBottomBeak` + id + `"></span>
<span id="dnaEyesShape` + id + `"></span>
<span id="dnaDecorationPattern` + id + `"></span>
<span id="dnaDecorationAtEye` + id + `"></span>
<span id="dnaDecorationMid` + id + `"></span>
<span id="dnaDecorationSmall` + id + `"></span>
<span id="dnaAnimation` + id + `"></span><br>
<ul class="ml-4">
<li class="bottomList"><span id="bottomeyetext`
+ id + `"></span></li>
<li class="bottomList"><span id="bottomdecorationpatterntext`
+ id + `"></span></li>
<li class="bottomList"><span id="bottomanimationtext`
+ id + `"></span></li>
</ul>
<div align="center">SIRE</div>
</b>
</div>
</div>`
$('#sireDisplay').empty();
$('#sireDisplay').append(boxDiv);
};
function childBox(id) {
var boxDiv = `<div style='transform: scaleX(0.8)' id="childBox" class="col-lg-6 m-2 CatalogBox light-b-shadow">
<div style='transform: scale(0.8) scaleX(1.2)' class="bird">
<div class="tail">
<div class="tail_top"></div>
<div class="tail_middle"></div>
<div class="tail_bottom"></div>
</div>
<div class="feather">
<div class="feather_top"></div>
<div class="feather_bottom"></div>
</div>
<div class="bird_body">
<div class="bird_body bird_body_inner"></div>
<div class="deco_1"></div>
<div class="deco_2"></div>
<div class="deco_3"></div>
<div class="deco_4"></div>
</div>
<div class="belly"></div>
<div class="face">
<div class="eye eye_right">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="eye eye_left">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="beak">
<div class="beak_upper"></div>
<div class="beak_lower"></div>
</div>
</div>
</div>
<br>
<div class="dnaDiv">
<b>
<div id="idData">
ID:
<span>` + id + `</span>
</div>
<div id="genData">
GEN:
<span id="generation` + id + `"></span>
</div><br>
<div id="mumData">
MUM:
<span id="mum` + id + `"></span>
</div>
<div id="dadData">
DAD:
<span align="right" id="dad` + id + `"></span><br>
</div><br>
DNA:
<span id="dnaTopFeather` + id + `"></span>
<span id="dnaBodyFeather` + id + `"></span>
<span id="dnaTopBeak` + id + `"></span>
<span id="dnaBottomBeak` + id + `"></span>
<span id="dnaEyesShape` + id + `"></span>
<span id="dnaDecorationPattern` + id + `"></span>
<span id="dnaDecorationAtEye` + id + `"></span>
<span id="dnaDecorationMid` + id + `"></span>
<span id="dnaDecorationSmall` + id + `"></span>
<span id="dnaAnimation` + id + `"></span><br>
<ul class="ml-4">
<li class="bottomList"><span id="bottomeyetext`
+ id + `"></span></li>
<li class="bottomList"><span id="bottomdecorationpatterntext`
+ id + `"></span></li>
<li class="bottomList"><span id="bottomanimationtext`
+ id + `"></span></li>
</ul>
<div align="center">NEWBORN!</div>
</b>
</div>
</div>`
$('#childDisplay').empty();
$('#childDisplay').append(boxDiv);
};
function modalBox(id) {
var boxDiv = `<div id="BirdBox` + id + `" class="col-lg-3 CatalogBox m-2 light-b-shadow">
<div class="bird">
<div class="tail">
<div class="tail_top"></div>
<div class="tail_middle"></div>
<div class="tail_bottom"></div>
</div>
<div class="feather">
<div class="feather_top"></div>
<div class="feather_bottom"></div>
</div>
<div class="bird_body">
<div class="bird_body bird_body_inner"></div>
<div class="deco_1"></div>
<div class="deco_2"></div>
<div class="deco_3"></div>
<div class="deco_4"></div>
</div>
<div class="belly"></div>
<div class="face">
<div class="eye eye_right">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="eye eye_left">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="beak">
<div class="beak_upper"></div>
<div class="beak_lower"></div>
</div>
</div>
</div>
<br>
<div class="dnaDiv">
<b>
<div id="idData">
ID:
<span>` + id + `</span>
</div>
<div id="genData">
GEN:
<span id="generation` + id + `"></span>
</div><br>
<div id="mumData">
MUM:
<span id="mum` + id + `"></span>
</div>
<div id="dadData">
DAD:
<span align="right" id="dad` + id + `"></span><br>
</div><br>
DNA:
<span id="dnaTopFeather` + id + `"></span>
<span id="dnaBodyFeather` + id + `"></span>
<span id="dnaTopBeak` + id + `"></span>
<span id="dnaBottomBeak` + id + `"></span>
<span id="dnaEyesShape` + id + `"></span>
<span id="dnaDecorationPattern` + id + `"></span>
<span id="dnaDecorationAtEye` + id + `"></span>
<span id="dnaDecorationMid` + id + `"></span>
<span id="dnaDecorationSmall` + id + `"></span>
<span id="dnaAnimation` + id + `"></span><br>
<ul class="ml-4">
<li class="bottomList"><span id="bottomeyetext`
+ id + `"></span></li>
<li class="bottomList"><span id="bottomdecorationpatterntext`
+ id + `"></span></li>
<li class="bottomList"><span id="bottomanimationtext`
+ id + `"></span></li>
</ul>
</b>
</div>
</div>`
$('.row').append(boxDiv);
};

183
client/assets/js/catalog.js Normal file
View File

@ -0,0 +1,183 @@
var balance;
var ids;
var onSale;
var toDisplay;
$(document).ready( async () => {//when page is loaded, get latest instance of blockchain
await connectWallet();
await onlyOwnerAccess();
balance = await returnBalance();
displayBalance(balance);
ids = await getBirdsOfOwner();
onSale = await getBirdsOnSale();
if (onSale == "") {
toDisplay = ids
;
} else {
toDisplay = ids
.filter(x => !onSale.includes(x));//all birds of this user not on sale
}
await buildCatalog(toDisplay);
activateMouseListeners();
});
function displayBalance(balance) {
$('#fundsAvailable').html("You have " + balance + " ETH available from bird sales. ");
};
function appendBirdToCatalog(dna, id) {
catalogBox(id); //class is defined and set in rendering.js
renderBird(`#BirdBox${id}`, birdDna(dna), id);
};
function catalogBox(id) {
var boxDiv = `<div id="BirdBox` + id + `" class="col-lg-3 catalogBox m-2 light-b-shadow">
<div class="bird">
<div class="tail">
<div class="tail_top"></div>
<div class="tail_middle"></div>
<div class="tail_bottom"></div>
</div>
<div class="feather">
<div class="feather_top"></div>
<div class="feather_bottom"></div>
</div>
<div class="bird_body">
<div class="bird_body bird_body_inner"></div>
<div class="deco_1"></div>
<div class="deco_2"></div>
<div class="deco_3"></div>
<div class="deco_4"></div>
</div>
<div class="belly"></div>
<div class="face">
<div class="eye eye_right">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="eye eye_left">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="beak">
<div class="beak_upper"></div>
<div class="beak_lower"></div>
</div>
</div>
</div>
<br>
<div class="dnaDiv">
<b>
<div id="idData">
ID:
<span>` + id + `</span>
</div>
<div id="genData">
GEN:
<span id="generation` + id + `"></span>
</div><br>
<div id="mumData">
MUM:
<span id="mum` + id + `"></span>
</div>
<div id="dadData">
DAD:
<span align="right" id="dad` + id + `"></span><br>
</div><br>
DNA:
<span id="dnaTopFeather` + id + `"></span>
<span id="dnaBodyFeather` + id + `"></span>
<span id="dnaTopBeak` + id + `"></span>
<span id="dnaBottomBeak` + id + `"></span>
<span id="dnaEyesShape` + id + `"></span>
<span id="dnaDecorationPattern` + id + `"></span>
<span id="dnaDecorationAtEye` + id + `"></span>
<span id="dnaDecorationMid` + id + `"></span>
<span id="dnaDecorationSmall` + id + `"></span>
<span id="dnaAnimation` + id + `"></span><br>
<ul class="ml-4">
<li class="bottomList"><span id="bottomeyetext`
+ id + `"></span></li>
<li class="bottomList"><span id="bottomdecorationpatterntext`
+ id + `"></span></li>
<li class="bottomList"><span id="bottomanimationtext`
+ id + `"></span></li>
</ul>
</b>
<div class="input-group mb-3">
<input id="birdPrice` + id + `" type="text"
class="form-control" placeholder="Amount in ETH"
aria-label="Amount in ETH" aria-describedby="button-addon2">
<div class="input-group-append">
<button id="offerButton` + id + `"
class="btn btn-success submitButton"
type="button" id="button-addon2">Submit Offer
</button>
</div>
</div>
</div>
</div>`
$('.row').append(boxDiv);
};
//Listener for withdraw button
$('#withdrawButton').click(async ()=>{
if(balance > 0) {
$('#withdrawButton').hide();
await withdraw();
location.reload();
};
});
//Listeners for offer buttons
function activateCatalogEventListeners() {
$(`[id^='birdPrice']`).keypress(async function(e) {
if ( e.which == 13 ) {//both enter buttons have '13'.
await initializeMarketplace();//allow Marketplace contract to handle offers.
var id = $(this).attr("id").substring(9);//extract id from HTML.
var price = $(this).val();//get price of the bird with the same id as the button
if (isNaN(price)) {
alert("Please enter a number!")
} else if (price <= 0) {
alert("Please enter a positive number!")
} else{
$(`#birdPrice${id}`).hide();
$(`#offerButton${id}`).hide();
await sellBird(price, id);
$(`#BirdBox${id}`).remove();//remove bird from DOM
};
};
});
$(`[id^='offerButton']`).on("click", async function() {
await initializeMarketplace();//allow Marketplace contract to handle offers.
var id = $(this).attr("id").substring(11);//extract id from HTML.
var price = $(`#birdPrice${id}`).val();//get price of the bird with the same id as the button
if (isNaN(price)) {
alert("Please enter a number!")
} else if (price <= 0) {
alert("Please enter a positive number!")
} else{
$(`#birdPrice${id}`).hide();
$(`#offerButton${id}`).hide();
await sellBird(price, id);
$(`#BirdBox${id}`).remove();//remove bird from DOM
};
});
};
//Listener for eye animation
function activateMouseListeners() {
$('.CatalogBox').on("mousemove", () => {
var eyeballs = $('.eyesFollow');
document.onmousemove = function(event) {
var x = event.clientX * 65 / window.innerWidth + "%";
var y = event.clientY * 65 / window.innerHeight + "%";
for (let i = 0; i < eyeballs.length; i++) {
eyeballs[i].style.left = x;
eyeballs[i].style.top = y;
};
};
});
};

106
client/assets/js/colors.js Normal file
View File

@ -0,0 +1,106 @@
var colors = {
00: "ae494f",
01: "9a3031",
02: "8cd42e",
03: "a0417a",
04: "91c656",
05: "299f7a",
06: "c65d1e",
07: "b2bbd6",
08: "2d4024",
09: "4b5715",
10: "ffcc80",
11: "3f1174",
12: "b22a90",
13: "fff3e0",
14: "4c858b",
15: "18bebe",
16: "b5044b",
17: "d6b1d4",
18: "fecb40",
19: "748882",
20: "4a3c95",
21: "482916",
22: "267bf0",
23: "5af7e2",
24: "adeacc",
25: "cf2b03",
26: "b3c459",
27: "353f99",
28: "5d4993",
29: "ba8d15",
30: "da2457",
31: "ff17fe",
32: "d6e81d",
33: "daf2db",
34: "19b510",
35: "ab060c",
36: "b7c36a",
37: "8cb175",
38: "bdce32",
39: "f2e0ba",
40: "a2f8a5",
41: "64bf50",
42: "f1a771",
43: "4982a9",
44: "f66c41",
45: "2fe802",
46: "bda142",
47: "8342ff",
48: "2b4ab4",
49: "ad4595",
50: "bae4f9",
51: "b76d01",
52: "8e8207",
53: "285b9f",
54: "c4422a",
55: "ce000f",
56: "e3a0cc",
57: "ce000f",
58: "656ccf",
59: "7c25f4",
60: "1e18d1",
61: "688a7d",
62: "1fe786",
63: "425716",
64: "4ac043",
65: "547836",
66: "24a216",
67: "fd9bba",
68: "24894d",
69: "c54b03",
70: "6fbdce",
71: "e28810",
72: "8805fb",
73: "e28810",
74: "c52f14",
75: "e31c54",
76: "d010eb",
77: "b83436",
78: "c294b6",
79: "564a6c",
80: "531bcf",
81: "e9b90d",
82: "3cd2ef",
83: "e9b90d",
84: "aa2639",
85: "86be6c",
86: "e62102",
87: "5471fc",
88: "5c0899",
89: "703c75",
90: "9a8e8f",
91: "8b9307",
92: "fcbc82",
93: "ea5978",
94: "b8e370",
95: "43474b",
96: "262d2b",
97: "ddd67e",
98: "344867",
99: "aacc32"
}
function allColors(){
return colors;
};

View File

@ -0,0 +1,4 @@
$(document).ready( async () => {//when page is loaded, get latest instance of blockchain
await connectWallet();
await onlyOwnerAccess();
});

2
client/assets/js/jquery-3.5.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

254
client/assets/js/market.js Normal file
View File

@ -0,0 +1,254 @@
var ids;
var onSale;
var inMarket;
var inOffers;
$(document).ready( async () => {//when page is loaded, get latest instance of blockchain
await connectWallet();
await onlyOwnerAccess();
ids = await getBirdsOfOwner();
onSale = await getBirdsOnSale();
inMarket = onSale.filter(x => !ids.includes(x));//offers of other users
inMarket = inMarket.filter(x => !["0"].includes(x));//remove Bird0
inOffers = onSale.filter(x => ids.includes(x));//user's offers
await buildOffers(inOffers);//build offers
await buildMarket(inMarket);//build market
activateMouseListeners();
});
async function appendBirdToMarket(dna, id) {
var price = await getPrice(id);
marketBox(price, id);
renderBird(`#BirdBox${id}`, birdDna(dna), id);
};
async function appendBirdToOffers(dna, id) {
var price = await getPrice(id);
offerBox(price, id);
renderBird(`#BirdBox${id}`, birdDna(dna), id);
};
function marketBox(price, id) {//used for offers of other users
var boxDiv = `<div id="BirdBox` + id + `" class="col-lg-3 buyBox CatalogBox m-2 light-b-shadow">
<div class="bird">
<div class="tail">
<div class="tail_top"></div>
<div class="tail_middle"></div>
<div class="tail_bottom"></div>
</div>
<div class="feather">
<div class="feather_top"></div>
<div class="feather_bottom"></div>
</div>
<div class="bird_body">
<div class="bird_body bird_body_inner"></div>
<div class="deco_1"></div>
<div class="deco_2"></div>
<div class="deco_3"></div>
<div class="deco_4"></div>
</div>
<div class="belly"></div>
<div class="face">
<div class="eye eye_right">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="eye eye_left">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="beak">
<div class="beak_upper"></div>
<div class="beak_lower"></div>
</div>
</div>
</div>
<br>
<div class="dnaDiv">
<b>
<div id="idData">
ID:
<span>` + id + `</span>
</div>
<div id="genData">
GEN:
<span id="generation` + id + `"></span>
</div><br>
<div id="mumData">
MUM:
<span id="mum` + id + `"></span>
</div>
<div id="dadData">
DAD:
<span align="right" id="dad` + id + `"></span><br>
</div><br>
DNA:
<span id="dnaTopFeather` + id + `"></span>
<span id="dnaBodyFeather` + id + `"></span>
<span id="dnaTopBeak` + id + `"></span>
<span id="dnaBottomBeak` + id + `"></span>
<span id="dnaEyesShape` + id + `"></span>
<span id="dnaDecorationPattern` + id + `"></span>
<span id="dnaDecorationAtEye` + id + `"></span>
<span id="dnaDecorationMid` + id + `"></span>
<span id="dnaDecorationSmall` + id + `"></span>
<span id="dnaAnimation` + id + `"></span><br>
<ul class="ml-4">
<li class="bottomList"><span id="bottomeyetext`
+ id + `"></span></li>
<li class="bottomList"><span id="bottomdecorationpatterntext`
+ id + `"></span></li>
<li class="bottomList"><span id="bottomanimationtext`
+ id + `"></span></li>
</ul>
<div align="center">
ASKING PRICE: ` + price + ` ETH
</div>
</b>
<div class="input-group mb-3">
<div class="input-group-append">
<button id="buyButton` + id + `"
class="btn btn-success buyButton rounded-lg"
type="button" id="button-addon2">Buy Bird</button>
</div>
</div>
</div>
</div>`
$('.marketOffers').append(boxDiv);
};
function offerBox(price, id) {//used for offers of current user
var boxDiv = `<div id="BirdBox` + id + `" class="col-lg-3 offerBox CatalogBox m-2 light-b-shadow">
<div class="bird">
<div class="tail">
<div class="tail_top"></div>
<div class="tail_middle"></div>
<div class="tail_bottom"></div>
</div>
<div class="feather">
<div class="feather_top"></div>
<div class="feather_bottom"></div>
</div>
<div class="bird_body">
<div class="bird_body bird_body_inner"></div>
<div class="deco_1"></div>
<div class="deco_2"></div>
<div class="deco_3"></div>
<div class="deco_4"></div>
</div>
<div class="belly"></div>
<div class="face">
<div class="eye eye_right">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="eye eye_left">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="beak">
<div class="beak_upper"></div>
<div class="beak_lower"></div>
</div>
</div>
</div>
<br>
<div class="dnaDiv">
<b>
<div id="idData">
ID:
<span>` + id + `</span>
</div>
<div id="genData">
GEN:
<span id="generation` + id + `"></span>
</div><br>
<div id="mumData">
MUM:
<span id="mum` + id + `"></span>
</div>
<div id="dadData">
DAD:
<span align="right" id="dad` + id + `"></span><br>
</div><br>
DNA:
<span id="dnaTopFeather` + id + `"></span>
<span id="dnaBodyFeather` + id + `"></span>
<span id="dnaTopBeak` + id + `"></span>
<span id="dnaBottomBeak` + id + `"></span>
<span id="dnaEyesShape` + id + `"></span>
<span id="dnaDecorationPattern` + id + `"></span>
<span id="dnaDecorationAtEye` + id + `"></span>
<span id="dnaDecorationMid` + id + `"></span>
<span id="dnaDecorationSmall` + id + `"></span>
<span id="dnaAnimation` + id + `"></span><br>
<ul class="ml-4">
<li class="bottomList"><span id="bottomeyetext`
+ id + `"></span></li>
<li class="bottomList"><span id="bottomdecorationpatterntext`
+ id + `"></span></li>
<li class="bottomList"><span id="bottomanimationtext`
+ id + `"></span></li>
</ul>
<div align="center">
ASKING PRICE: ` + price + ` ETH
</div>
</b>
<div class="input-group mb-3">
<div class="input-group-append">
<button id="cancelButton` + id + `"
class="btn btn-danger cancelButton rounded-lg"
type="button" id="button-addon2">Cancel Offer
</button>
</div>
</div>
</div>
</div>`
$('.myOffers').append(boxDiv);
};
//Listener for eye animation
function activateMouseListeners() {
$('.CatalogBox').on("mousemove", () => {
var eyeballs = $('.eyesFollow');
document.onmousemove = function(event) {
var x = event.clientX * 65 / window.innerWidth + "%";
var y = event.clientY * 65 / window.innerHeight + "%";
for (let i = 0; i < eyeballs.length; i++) {
eyeballs[i].style.left = x;
eyeballs[i].style.top = y;
};
};
});
};
//Listeners for buttons
async function activateBuyButtonListeners() {
if(await checkPause()) {
$(`[id^='buyButton']`).hide();
} else {
$(`[id^='buyButton']`).show();
$(`[id^='buyButton']`).on("click", async function() {
await initializeMarketplace();
//make sure marketplace contract is approved as operator for user
var id = $(this).attr("id").substring(9);//extract bird ID from HTML
var price = await getPrice(id);
$(`#buyButton${id}`).hide();
await buyBird(price, id);
$(`#BirdBox${id}`).remove();//remove bird from DOM
});
};
};
function activateCancelButtonListeners() {
$(`[id^='cancelButton']`).on("click", async function() {
await initializeMarketplace();
//make sure marketplace contract is approved as operator for user
var id = $(this).attr("id").substring(12);//extract bird ID from HTML
$(`#cancelButton${id}`).hide();
await removeOffer(id);
$(`#BirdBox${id}`).remove();//remove bird from DOM
});
};

View File

@ -0,0 +1,431 @@
var colors = Object.values(allColors());
function birdDna(dna) {
var dnaObject = {
"topFeatherColor": dna.genes.substring(0, 2),
"bodyFeatherColor": dna.genes.substring(2, 4),
"topBeakColor": dna.genes.substring(4, 6),
"bottomBeakColor": dna.genes.substring(6, 8),
"eyesShape": parseInt(dna.genes.substring(8, 9)),
"decorationPattern": parseInt(dna.genes.substring(9, 10)),
"decorationColor": dna.genes.substring(10, 12),
"decorationMidColor": dna.genes.substring(12, 14),
"decorationSmallColor": dna.genes.substring(14, 16),
"animation": parseInt(dna.genes.substring(16, 17)),
"generation": dna.generation,
"mum": dna.mumId,
"dad": dna.dadId
};
return dnaObject;
};
function renderBird(boxId, dna, id){
topFeatherColor(boxId, colors[dna.topFeatherColor], dna.topFeatherColor, id);
bodyFeatherColor(boxId, colors[dna.bodyFeatherColor],dna.bodyFeatherColor, id);
topBeakColor(boxId, colors[dna.topBeakColor],dna.topBeakColor, id);
bottomBeakColor(boxId, colors[dna.bottomBeakColor],dna.bottomBeakColor, id);
eyesVariation(boxId, dna.eyesShape, id);
decorationVariation(boxId, dna.decorationPattern, id);
decorationMainColor(boxId, colors[dna.decorationColor],dna.decorationColor, id);
middleColor(boxId, colors[dna.decorationMidColor],dna.decorationMidColor, id);
smallColor(boxId, colors[dna.decorationSmallColor],dna.decorationSmallColor, id);
animationVariation(boxId, dna.animation, id);
printGeneration(dna.generation, id);
printMum(dna.mum, id);
printDad(dna.dad, id);
};
function topFeatherColor(boxId, color, code, id) {
$(`${boxId} .feather_top`).css('background', '#' + color);
$(`${boxId} .feather_bottom`).css('background', '#' + color);
$('#dnaTopFeather' + id).html(code);
};
function bodyFeatherColor(boxId, color, code, id) {
$(`${boxId} .bird_body_inner`).css('background', '#' + color);
$('#dnaBodyFeather' + id).html(code);
};
function topBeakColor(boxId, color, code, id) {
$(`${boxId} .beak_upper`).css('background', '#' + color);
$('#dnaTopBeak' + id).html(code);
};
function bottomBeakColor(boxId, color, code, id) {
$(`${boxId} .beak_lower`).css('background', '#' + color);
$('#dnaBottomBeak' + id).html(code);
};
function eyesVariation(boxId, num, id) {
$('#dnaEyesShape' + id).html(num);
switch (num) {
case 0:
basicEyes(boxId);
$('#bottomeyetext' + id).html('Basic Eyes');
break;
case 1:
basicEyes(boxId);
$('#bottomeyetext' + id).html('Chilled Eyes');
eyesType1(boxId);
break;
case 2:
basicEyes(boxId);
$('#bottomeyetext' + id).html('Eyes Turned Upwards');
eyesType2(boxId);
break;
case 3:
basicEyes(boxId);
$('#bottomeyetext' + id).html('Eyes Turned Right');
eyesType3(boxId);
break;
case 4:
basicEyes(boxId);
$('#bottomeyetext' + id).html('Eyes Turned Left');
eyesType4(boxId);
break;
case 5:
basicEyes(boxId);
$('#bottomeyetext' + id).html('Dazzled Eyes');
eyesType5(boxId);
break;
case 6:
basicEyes(boxId);
$('#bottomeyetext' + id).html('Eye Slits');
eyesType6(boxId);
break;
case 7:
basicEyes(boxId);
$('#bottomeyetext' + id).html('Masked Eyes');
eyesType7(boxId);
break;
default:
basicEyes(boxId);
$('#bottomeyetext' + id).html('Basic Eyes');
};
};
function basicEyes(boxId) {
$(`${boxId} .eye`).css({'border-top': 'none', 'border-bottom': 'none',
'border-left': 'none', 'border-right': 'none', 'border': '0.9em black solid'});
$(`${boxId} .eye_right .eyebrow`).css({'left': '-1em', 'top': '-1.5em'});
$(`${boxId} .eye_left .eyebrow`).css({'left': '-3em', 'top': '-1.5em'});
$(`${boxId} .eye_right .pupil`).css({'left': '1.5em', 'top': '3em'});
$(`${boxId} .eye_left .pupil`).css({'left': '5em', 'top': '3em'});
};
function eyesType1(boxId) {//Chilled
$(`${boxId} .eye`).css('border-top', '4em solid');
$(`${boxId} .eye_right .eyebrow`).css({'left': '-1em', 'top': '-4.5em'});
$(`${boxId} .eye_left .eyebrow`).css({'left': '-3em', 'top': '-4.5em'});
$(`${boxId} .eye_right .pupil`).css({'left': '1.5em', 'top': '1em'});
$(`${boxId} .eye_left .pupil`).css({'left': '5em', 'top': '1em'});
};
function eyesType2(boxId) {//Up
$(`${boxId} .eye`).css('border-bottom', '4em solid');
$(`${boxId} .eye_right .eyebrow`).css({'left': '-1em', 'top': '-2em'});
$(`${boxId} .eye_left .eyebrow`).css({'left': '-3em', 'top': '-2em'});
$(`${boxId} .eye_right .pupil`).css({'left': '1.5em', 'top': '2em'});
$(`${boxId} .eye_left .pupil`).css({'left': '5em', 'top': '2em'});
};
function eyesType3(boxId) {//Right
$(`${boxId} .eye`).css('border-left', '2.5em solid');
$(`${boxId} .eye_right .eyebrow`).css({'left': '-1em', 'top': '-1.5em'});
$(`${boxId} .eye_left .eyebrow`).css({'left': '-3em', 'top': '-1.5em'});
$(`${boxId} .eye_right .pupil`).css({'left': '5em', 'top': '3em'});
$(`${boxId} .eye_left .pupil`).css({'left': '5em', 'top': '3em'});
};
function eyesType4(boxId) {//Left
$(`${boxId} .eye`).css('border-right', '2.5em solid');
$(`${boxId} .eye_right .eyebrow`).css({'left': '-1em', 'top': '-1.5em'});
$(`${boxId} .eye_left .eyebrow`).css({'left': '-3em', 'top': '-1.5em'});
$(`${boxId} .eye_right .pupil`).css({'left': '0em', 'top': '3em'});
$(`${boxId} .eye_left .pupil`).css({'left': '0em', 'top': '3em'});
};
function eyesType5(boxId) {//Dazzled
$(`${boxId} .eye`).css({'border-top': '4em solid', 'border-bottom': '4em solid'});
$(`${boxId} .eye_right .eyebrow`).css({'left': '-1em', 'top': '-5.5em'});
$(`${boxId} .eye_left .eyebrow`).css({'left': '-3em', 'top': '-5.5em'});
$(`${boxId} .eye_right .pupil`).css({'left': '3em', 'top': '0em'});
$(`${boxId} .eye_left .pupil`).css({'left': '3em', 'top': '0em'});
};
function eyesType6(boxId) {//Slit
$(`${boxId} .eye`).css({'border-top': '4em solid', 'border-left': '4em solid',
'border-right': '4em solid'});
$(`${boxId} .eye_right .eyebrow`).css({'left': '-4em', 'top': '-5em'});
$(`${boxId} .eye_left .eyebrow`).css({'left': '-6em', 'top': '-5em'});
$(`${boxId} .eye_right .pupil`).css({'left': '-0.1em', 'top': '1em'});
$(`${boxId} .eye_left .pupil`).css({'left': '-0.1em', 'top': '1em'});
};
function eyesType7(boxId) {//Mask
$(`${boxId} .eye`).css('border', '3em solid');
$(`${boxId} .eye_right .eyebrow`).css({'left': '-3em', 'top': '-5em'});
$(`${boxId} .eye_left .eyebrow`).css({'left': '-5em', 'top': '-5em'});
$(`${boxId} .eye_right .pupil`).css({'left': '1em', 'top': '1em'});
$(`${boxId} .eye_left .pupil`).css({'left': '1em', 'top': '1em'});
};
function decorationVariation(boxId, num, id) {
$('#dnaDecorationPattern' + id).html(num)
switch (num) {
case 0:
$('#bottomdecorationpatterntext' + id).html('Basic Decoration');
resetDecoration(boxId);
break;
case 1:
resetDecoration(boxId);
$('#bottomdecorationpatterntext' + id).html('Large Spots');
decorationType1(boxId);
break;
case 2:
resetDecoration(boxId);
$('#bottomdecorationpatterntext' + id).html('Maximum Spots');
decorationType2(boxId);
break;
case 3:
resetDecoration(boxId);
$('#bottomdecorationpatterntext' + id).html('Decoration only at Eyes');
decorationType3(boxId);
break;
case 4:
resetDecoration(boxId);
$('#bottomdecorationpatterntext' + id).html('Decoration on Back only');
decorationType4(boxId);
break;
case 5:
resetDecoration(id);
$('#bottomdecorationpatterntext' + id).html('No Decoration');
decorationType5(boxId);
break;
case 6:
resetDecoration(boxId);
$('#bottomdecorationpatterntext' + id).html('Cross Decoration');
decorationType6(boxId);
break;
case 7:
resetDecoration(boxId);
$('#bottomdecorationpatterntext' + id).html('Cross & Eyes Decoration');
decorationType7(boxId);
break;
default:
resetDecoration(boxId);
$('#bottomdecorationpatterntext' + id).html('Basic Decoration');
};
};
function resetDecoration(boxId) {
$(`${boxId} .deco_1`).css({'display': 'initial', 'transform':
'rotate(-25deg) scaleY(1) translateX(0em) translateY(0em)'});
$(`${boxId} .deco_2`).css({'display': 'initial', 'transform':
'rotate(-15deg) scaleY(1) translateX(0em) translateY(0em)'});
$(`${boxId} .deco_3`).css({'display': 'initial', 'transform':
'rotate(-10deg) scaleY(1) translateY(0em)'});
$(`${boxId} .deco_4`).css({'display': 'initial', 'transform':
'rotate(-10deg) scaleY(1) translateY(0em)'});
};
function decorationType1(boxId) {//Large
$(`${boxId} .deco_1`).css('transform', 'rotate(-25deg) scaleY(2)');
$(`${boxId} .deco_2`).css('transform', 'rotate(-15deg) scaleY(2)');
$(`${boxId} .deco_3`).css('transform', 'rotate(-10deg) scaleY(2)');
$(`${boxId} .deco_4`).css('transform', 'rotate(-10deg) scaleY(2)');
};
function decorationType2(boxId) {//Max
$(`${boxId} .deco_1`).css('transform', 'rotate(-25deg) scaleY(3) translateY(-2.5em)');
$(`${boxId} .deco_2`).css('transform', 'rotate(-15deg) scaleY(3) translateY(-2.5em)');
$(`${boxId} .deco_3`).css('transform', 'rotate(-10deg) scaleY(3) translateY(-2.5em)');
$(`${boxId} .deco_4`).css('transform', 'rotate(-10deg) scaleY(3) translateY(-1.8em)');
};
function decorationType3(boxId) {//Eyes Only
$(`${boxId} .deco_1`).css('display', 'none');
$(`${boxId} .deco_2`).css('display', 'none');
$(`${boxId} .deco_3`).css('transform', 'rotate(-10deg) scaleY(3) translateY(-2.5em)');
$(`${boxId} .deco_4`).css('transform', 'rotate(-10deg) scaleY(3) translateY(-1.8em)');
};
function decorationType4(boxId) {//Back Only
$(`${boxId} .deco_1`).css('transform', 'rotate(-25deg) scaleY(3) translateY(-2.5em)');
$(`${boxId} .deco_2`).css('transform', 'rotate(-15deg) scaleY(3) translateY(-2.5em)');
$(`${boxId} .deco_3`).css('display', 'none');
$(`${boxId} .deco_4`).css('display', 'none');
};
function decorationType5(boxId) {//None
$(`${boxId} .deco_1`).css('display', 'none');
$(`${boxId} .deco_2`).css('display', 'none');
$(`${boxId} .deco_3`).css('display', 'none');
$(`${boxId} .deco_4`).css('display', 'none');
};
function decorationType6(boxId) {//Cross
$(`${boxId} .deco_1`).css('transform',
'rotate(90deg) scaleY(3) translateX(-9em) translateY(-0.5em)');
$(`${boxId} .deco_2`).css('transform',
'rotate(0deg) scaleY(3) translateX(-3.5em) translateY(-2.5em)');
$(`${boxId} .deco_3`).css('display', 'none');
$(`${boxId} .deco_4`).css('display', 'none');
}
;
function decorationType7(boxId) {//Cross & Eyes
$(`${boxId} .deco_1`).css('transform',
'rotate(90deg) scaleY(3) translateX(-9em) translateY(-0.5em)');
$(`${boxId} .deco_2`).css('transform',
'rotate(0deg) scaleY(3) translateX(-3.5em) translateY(-2.5em)');
$(`${boxId} .deco_3`).css('transform', 'rotate(-10deg) scaleY(2)');
$(`${boxId} .deco_4`).css('transform', 'rotate(-10deg) scaleY(2)');
};
function decorationMainColor(boxId, color, code, id) {
$(`${boxId} .deco_3`, `${boxId} .deco_4`).css('background', '#' + color);
$('#dnaDecorationAtEye' + id).html(code);
};
function middleColor(boxId, color, code, id) {
$(`${boxId} .deco_2`).css('background', '#' + color);
$('#dnaDecorationMid' + id).html(code);
};
function smallColor(boxId, color, code, id) {
$(`${boxId} .deco_1`).css('background', '#' + color);
$('#dnaDecorationSmall' + id).html(code);
};
function animationVariation(boxId, num, id) {
$('#dnaAnimation' + id).html(num);
switch (num) {
case 0:
resetAnimation(boxId);
$('#bottomanimationtext' + id).html('No animation');
break;
case 1:
resetAnimation(boxId);
$('#bottomanimationtext' + id).html('Animation: Kick');
animationType1(boxId);
break;
case 2:
resetAnimation(boxId);
$('#bottomanimationtext' + id).html('Animation: Float');
animationType2(boxId);
break;
case 3:
resetAnimation(boxId);
$('#bottomanimationtext' + id).html('Animation: Compress');
animationType3(boxId);
break;
case 4:
resetAnimation(boxId);
$('#bottomanimationtext' + id).html('Animation: Speak');
animationType4(boxId);
break;
case 5:
resetAnimation(boxId);
$('#bottomanimationtext' + id).html('Animation: Wag');
animationType5(boxId);
break;
case 6:
resetAnimation(boxId);
$('#bottomanimationtext' + id).html('Animation: Attention');
animationType6(boxId);
break;
case 7:
resetAnimation(boxId);
$('#bottomanimationtext' + id).html('Combi Animation');
animationType7(boxId);
break;
case 8:
resetAnimation(boxId);
$('#bottomanimationtext' + id).html('Eyes Follow Mouse');
animationType8(boxId);
break;
default:
resetAnimation(boxId);
$('#bottomanimationtext' + id).html('No animation');
};
};
function resetAnimation(boxId) {
$(`${boxId} .bird`).removeClass('slowRotateBird floatingBird compressingBird');
$(`${boxId} .beak_upper`).removeClass('upperSpeakingBird');
$(`${boxId} .beak_lower`).removeClass('lowerSpeakingBird');
$(`${boxId} .tail_top`).removeClass('topWaggingTail');
$(`${boxId} .tail_middle`).removeClass('middleWaggingTail');
$(`${boxId} .tail_bottom`).removeClass('bottomWaggingTail');
$(`${boxId} .feather_top`).removeClass('topAttention');
$(`${boxId} .feather_bottom`).removeClass('bottomAttention');
$(`${boxId} .pupil`).removeClass('eyesFollow');
};
function animationType1(boxId) {
$(`${boxId} .bird`).addClass('slowRotateBird');
};
function animationType2(boxId) {
$(`${boxId} .bird`).addClass('floatingBird');
};
function animationType3(boxId) {
$(`${boxId} .bird`).addClass('compressingBird');
};
function animationType4(boxId) {
$(`${boxId} .beak_upper`).addClass('upperSpeakingBird');
$(`${boxId} .beak_lower`).addClass('lowerSpeakingBird');
};
function animationType5(boxId) {
$(`${boxId} .tail_top`).addClass('topWaggingTail');
$(`${boxId} .tail_middle`).addClass('middleWaggingTail');
$(`${boxId} .tail_bottom`).addClass('bottomWaggingTail');
};
function animationType6(boxId) {
$(`${boxId} .feather_top`).addClass('topAttention');
$(`${boxId} .feather_bottom`).addClass('bottomAttention');
};
function animationType7(boxId) {
$(`${boxId} .bird`).addClass('floatingBird');
$(`${boxId} .beak_upper`).addClass('upperSpeakingBird');
$(`${boxId} .beak_lower`).addClass('lowerSpeakingBird');
$(`${boxId} .tail_top`).addClass('topWaggingTail');
$(`${boxId} .tail_middle`).addClass('middleWaggingTail');
$(`${boxId} .tail_bottom`).addClass('bottomWaggingTail');
$(`${boxId} .feather_top`).addClass('topAttention');
$(`${boxId} .feather_bottom`).addClass('bottomAttention');
};
function animationType8(boxId) {
basicEyes(boxId);
$(`${boxId} .pupil`).addClass('eyesFollow');
};
function printGeneration(genNo, id) {
$('#generation' + id).html(genNo);
};
function printMum(mum, id) {
var print;
if (mum == 0) {
print = 'n/a'
} else {
print = mum;
}
$('#mum' + id).html(print);
};
function printDad(dad, id) {
var print;
if (dad == 0) {
print = 'n/a'
} else {
print = dad;
};
$('#dad' + id).html(print);
};

548
client/assets/js/studio.js Normal file
View File

@ -0,0 +1,548 @@
var colors = Object.values(allColors());
const defaultDNA = {
"topFeatherColor": 23,
"bodyFeatherColor": 54,
"topBeakColor": 83,
"bottomBeakColor": 73,
"eyesShape": 0,
"decorationPattern": 0,
"decorationColor": 35,
"decorationMidColor": 35,
"decorationSmallColor": 35,
"animation": 0
};
$(document).ready( async () => {//when page is loaded, get latest instance of blockchain
$('.colorscreen').show();
$('.attributes').hide();
setDefaultDna();
await connectWallet();
await onlyOwnerAccess();
});
function setDefaultDna(){
$('#dnaTopFeather').html(defaultDNA.topFeatherColor);
$('#dnaBodyFeather').html(defaultDNA.bodyFeatherColor);
$('#dnaTopBeak').html(defaultDNA.topBeakColor);
$('#dnaBottomBeak').html(defaultDNA.bottomBeakColor);
$('#dnaEyesShape').html(defaultDNA.eyesShape);
$('#dnadecorationPattern').html(defaultDNA.decorationPattern);
$('#dnaDecorationAtEyes').html(defaultDNA.decorationColor);
$('#dnaDecorationMid').html(defaultDNA.decorationMidColor);
$('#dnaDecorationSmall').html(defaultDNA.decorationSmallColor);
$('#dnaAnimation').html(defaultDNA.animation);
renderBird(defaultDNA);
};
function renderBird(dna){
topFeatherColor(colors[dna.topFeatherColor],dna.topFeatherColor);
$('#topfeatherscolor').val(dna.topFeatherColor);
bodyFeatherColor(colors[dna.bodyFeatherColor],dna.bodyFeatherColor);
$('#bodyfeatherscolor').val(dna.bodyFeatherColor);
topBeakColor(colors[dna.topBeakColor],dna.topBeakColor);
$('#topbeakcolor').val(dna.topBeakColor);
bottomBeakColor(colors[dna.bottomBeakColor],dna.bottomBeakColor);
$('#bottombeakcolor').val(dna.bottomBeakColor);
eyesVariation(dna.eyesShape);
$('#eyesstyle').val(dna.eyesShape);
decorationVariation(dna.decorationPattern);
$('#decorationstyle').val(dna.decorationPattern);
decorationMainColor(colors[dna.decorationColor],dna.decorationColor);
$('#ateyescolor').val(dna.decorationColor);
middleColor(colors[dna.decorationMidColor],dna.decorationMidColor);
$('#middlecolor').val(dna.decorationMidColor);
smallColor(colors[dna.decorationSmallColor],dna.decorationSmallColor);
$('#smallcolor').val(dna.decorationSmallColor);
animationVariation(dna.animation);
$('#animationstyle').val(dna.animation);
};
function getDna(){//used when bird created on blockchain
var dna = '';
dna += $('#dnaTopFeather').html();
dna += $('#dnaBodyFeather').html();
dna += $('#dnaTopBeak').html();
dna += $('#dnaBottomBeak').html();
dna += $('#dnaEyesShape').html();
dna += $('#dnaDecorationPattern').html();
dna += $('#dnaDecorationAtEye').html();
dna += $('#dnaDecorationMid').html();
dna += $('#dnaDecorationSmall').html();
dna += $('#dnaAnimation').html();
return dna;
};
function setRandomDna(){
var randomDna = {
"topFeatherColor": Math.floor(Math.random()*90) + 10,// number from 10 to 99
"bodyFeatherColor": Math.floor(Math.random()*90) + 10,// number from 10 to 99
"topBeakColor": Math.floor(Math.random()*90) + 10,// number from 10 to 99
"bottomBeakColor": Math.floor(Math.random()*90) + 10,// number from 10 to 99
"eyesShape": Math.floor(Math.random()*8),// number from 0 to 7
"decorationPattern": Math.floor(Math.random()*8),// number from 0 to 7
"decorationColor": Math.floor(Math.random()*90) + 10,// number from 10 to 99
"decorationMidColor": Math.floor(Math.random()*90) + 10,// number from 10 to 99
"decorationSmallColor": Math.floor(Math.random()*90) + 10,// number from 10 to 99
"animation": Math.floor(Math.random()*9)// number from 0 to 8
};
renderBird(randomDna);//this will always return 17 digits for the Dna of a bird.
};
// Event listeners
$('#colorsButton').click(()=>{
$('.colorscreen').show();
$('.attributes').hide();
$('.bird').css('top', '15em');
});
$('#attributesButton').click(()=>{
$('.colorscreen').hide();
$('.attributes').show();
$('.bird').css('top', '25em');
});
$('#topfeatherscolor').change(()=>{
var colorVal = $('#topfeatherscolor').val();
topFeatherColor(colors[colorVal],colorVal);
});
$('#bodyfeatherscolor').change(()=>{
var colorVal = $('#bodyfeatherscolor').val();
bodyFeatherColor(colors[colorVal],colorVal);
});
$('#topbeakcolor').change(()=>{
var colorVal = $('#topbeakcolor').val();
topBeakColor(colors[colorVal],colorVal);
});
$('#bottombeakcolor').change(()=>{
var colorVal = $('#bottombeakcolor').val();
bottomBeakColor(colors[colorVal],colorVal);
});
$('#eyesstyle').change(()=>{
var shape = parseInt($('#eyesstyle').val());
eyesVariation(shape);
});
$('#decorationstyle').change(()=>{
var shape = parseInt($('#decorationstyle').val());
decorationVariation(shape);
});
$('#ateyescolor').change(()=>{
var colorVal = $('#ateyescolor').val();
decorationMainColor(colors[colorVal],colorVal);
});
$('#middlecolor').change(()=>{
var colorVal = $('#middlecolor').val();
middleColor(colors[colorVal],colorVal);
});
$('#smallcolor').change(()=>{
var colorVal = $('#smallcolor').val();
smallColor(colors[colorVal],colorVal);
});
$('#animationstyle').change(()=>{
var variation = parseInt($('#animationstyle').val());
animationVariation(variation);
});
$('#randomizeButton').click(()=>{
setRandomDna();
});
$('#defaultButton').click(()=>{
setDefaultDna();
});
$('#createButton').click(()=>{
createBird();
});
function topFeatherColor(color,code) {
$('.feather_top, .feather_bottom').css('background', '#' + color)
//This changes the color of the bird
$('#topfeatherstext').html('Code: '+ code)
//This updates text of the badge above the slider
$('#dnaTopFeather').html(code)
//This updates the DNA that is displayed below the bird
};
function bodyFeatherColor(color,code) {
$('.bird_body_inner').css('background', '#' + color)
$('#bodyfeatherstext').html('Code: '+ code)
$('#dnaBodyFeather').html(code)
};
function topBeakColor(color,code) {
$('.beak_upper').css('background', '#' + color)
$('#topbeaktext').html('Code: '+ code)
$('#dnaTopBeak').html(code)
};
function bottomBeakColor(color,code) {
$('.beak_lower').css('background', '#' + color)
$('#bottombeaktext').html('Code: '+ code)
$('#dnaBottomBeak').html(code)
};
function eyesVariation(num) {
$('#dnaEyesShape').html(num)
switch (num) {
case 0:
basicEyes();
$('#eyesshapetext').html('Basic');
break;
case 1:
basicEyes();
$('#eyesshapetext').html('Chilled');
eyesType1();
break;
case 2:
basicEyes();
$('#eyesshapetext').html('Up');
eyesType2();
break;
case 3:
basicEyes();
$('#eyesshapetext').html('Right');
eyesType3();
break;
case 4:
basicEyes();
$('#eyesshapetext').html('Left');
eyesType4();
break;
case 5:
basicEyes();
$('#eyesshapetext').html('Dazzled');
eyesType5();
break;
case 6:
basicEyes();
$('#eyesshapetext').html('Slit');
eyesType6();
break;
case 7:
basicEyes();
$('#eyesshapetext').html('Mask');
eyesType7();
break;
default:
basicEyes();
$('#eyesshapetext').html('Basic');
};
};
function basicEyes() {
$('.eye').css({'border-top': 'none', 'border-bottom': 'none', 'border-left':
'none', 'border-right': 'none', 'border': '0.9em black solid'});
$('.eye_right .eyebrow').css({'left': '-1em', 'top': '-1.5em'});
$('.eye_left .eyebrow').css({'left': '-3em', 'top': '-1.5em'});
$('.eye_right .pupil').css({'left': '1.5em', 'top': '3em'});
$('.eye_left .pupil').css({'left': '5em', 'top': '3em'});
};
function eyesType1() {//Chilled
$('.eye').css('border-top', '4em solid');
$('.eye_right .eyebrow').css({'left': '-1em', 'top': '-4.5em'});
$('.eye_left .eyebrow').css({'left': '-3em', 'top': '-4.5em'});
$('.eye_right .pupil').css({'left': '1.5em', 'top': '1em'});
$('.eye_left .pupil').css({'left': '5em', 'top': '1em'});
};
function eyesType2() {//Up
$('.eye').css('border-bottom', '4em solid');
$('.eye_right .eyebrow').css({'left': '-1em', 'top': '-2em'});
$('.eye_left .eyebrow').css({'left': '-3em', 'top': '-2em'});
$('.eye_right .pupil').css({'left': '1.5em', 'top': '2em'});
$('.eye_left .pupil').css({'left': '5em', 'top': '2em'});
};
function eyesType3() {//Right
$('.eye').css('border-left', '2.5em solid');
$('.eye_right .eyebrow').css({'left': '-1em', 'top': '-1.5em'});
$('.eye_left .eyebrow').css({'left': '-3em', 'top': '-1.5em'});
$('.eye_right .pupil').css({'left': '5em', 'top': '3em'});
$('.eye_left .pupil').css({'left': '5em', 'top': '3em'});
};
function eyesType4() {//Left
$('.eye').css('border-right', '2.5em solid');
$('.eye_right .eyebrow').css({'left': '-1em', 'top': '-1.5em'});
$('.eye_left .eyebrow').css({'left': '-3em', 'top': '-1.5em'});
$('.eye_right .pupil').css({'left': '0em', 'top': '3em'});
$('.eye_left .pupil').css({'left': '0em', 'top': '3em'});
};
function eyesType5() {//Dazzled
$('.eye').css({'border-top': '4em solid', 'border-bottom': '4em solid'});
$('.eye_right .eyebrow').css({'left': '-1em', 'top': '-5.5em'});
$('.eye_left .eyebrow').css({'left': '-3em', 'top': '-5.5em'});
$('.eye_right .pupil').css({'left': '3em', 'top': '0em'});
$('.eye_left .pupil').css({'left': '3em', 'top': '0em'});
};
function eyesType6() {//Slit
$('.eye').css({'border-top': '4em solid', 'border-left': '4em solid',
'border-right': '4em solid'});
$('.eye_right .eyebrow').css({'left': '-4em', 'top': '-5em'});
$('.eye_left .eyebrow').css({'left': '-6em', 'top': '-5em'});
$('.eye_right .pupil').css({'left': '-0.1em', 'top': '1em'});
$('.eye_left .pupil').css({'left': '-0.1em', 'top': '1em'});
};
function eyesType7() {//Mask
$('.eye').css('border', '3em solid');
$('.eye_right .eyebrow').css({'left': '-3em', 'top': '-5em'});
$('.eye_left .eyebrow').css({'left': '-5em', 'top': '-5em'});
$('.eye_right .pupil').css({'left': '1em', 'top': '1em'});
$('.eye_left .pupil').css({'left': '1em', 'top': '1em'});
};
function decorationVariation(num) {
$('#dnaDecorationPattern').html(num)
switch (num) {
case 0:
$('#decorationpatterntext').html('Basic');
basicDecoration();
break;
case 1:
basicDecoration();
$('#decorationpatterntext').html('Large');
decorationType1();
break;
case 2:
basicDecoration();
$('#decorationpatterntext').html('Max');
decorationType2();
break;
case 3:
basicDecoration();
$('#decorationpatterntext').html('Eyes Only');
decorationType3();
break;
case 4:
basicDecoration();
$('#decorationpatterntext').html('Back Only');
decorationType4();
break;
case 5:
basicDecoration();
$('#decorationpatterntext').html('None');
decorationType5();
break;
case 6:
basicDecoration();
$('#decorationpatterntext').html('Cross');
decorationType6();
break;
case 7:
basicDecoration();
$('#decorationpatterntext').html('Cross & Eyes');
decorationType7();
break;
default:
basicDecoration();
$('#decorationpatterntext').html('Basic');
};
};
function basicDecoration() {
$('.bird_body .deco_1').css({'display': 'initial', 'transform':
'rotate(-25deg) scaleY(1) translateX(0em) translateY(0em)'});
$('.bird_body .deco_2').css({'display': 'initial', 'transform':
'rotate(-15deg) scaleY(1) translateX(0em) translateY(0em)'});
$('.bird_body .deco_3').css({'display': 'initial', 'transform':
'rotate(-10deg) scaleY(1) translateY(0em)'});
$('.bird_body .deco_4').css({'display': 'initial', 'transform':
'rotate(-10deg) scaleY(1) translateY(0em)'});
};
function decorationType1() {//Large
$('.bird_body .deco_1').css('transform', 'rotate(-25deg) scaleY(2)');
$('.bird_body .deco_2').css('transform', 'rotate(-15deg) scaleY(2)');
$('.bird_body .deco_3').css('transform', 'rotate(-10deg) scaleY(2)');
$('.bird_body .deco_4').css('transform', 'rotate(-10deg) scaleY(2)');
};
function decorationType2() {//Max
$('.bird_body .deco_1').css('transform', 'rotate(-25deg) scaleY(3) translateY(-2.5em)');
$('.bird_body .deco_2').css('transform', 'rotate(-15deg) scaleY(3) translateY(-2.5em)');
$('.bird_body .deco_3').css('transform', 'rotate(-10deg) scaleY(3) translateY(-2.5em)');
$('.bird_body .deco_4').css('transform', 'rotate(-10deg) scaleY(3) translateY(-1.8em)');
};
function decorationType3() {//Eyes Only
$('.bird_body .deco_1').css('display', 'none');
$('.bird_body .deco_2').css('display', 'none');
$('.bird_body .deco_3').css('transform', 'rotate(-10deg) scaleY(3) translateY(-2.5em)');
$('.bird_body .deco_4').css('transform', 'rotate(-10deg) scaleY(3) translateY(-1.8em)');
};
function decorationType4() {//Back Only
$('.bird_body .deco_1').css('transform', 'rotate(-25deg) scaleY(3) translateY(-2.5em)');
$('.bird_body .deco_2').css('transform', 'rotate(-15deg) scaleY(3) translateY(-2.5em)');
$('.bird_body .deco_3').css('display', 'none');
$('.bird_body .deco_4').css('display', 'none');
};
function decorationType5() {//None
$('.bird_body .deco_1').css('display', 'none');
$('.bird_body .deco_2').css('display', 'none');
$('.bird_body .deco_3').css('display', 'none');
$('.bird_body .deco_4').css('display', 'none');
};
function decorationType6() {//Cross
$('.bird_body .deco_1').css('transform',
'rotate(90deg) scaleY(3) translateX(-9em) translateY(-0.5em)');
$('.bird_body .deco_2').css('transform',
'rotate(0deg) scaleY(3) translateX(-3.5em) translateY(-2.5em)');
$('.bird_body .deco_3').css('display', 'none');
$('.bird_body .deco_4').css('display', 'none');
};
function decorationType7() {//Cross & Eyes
$('.bird_body .deco_1').css('transform',
'rotate(90deg) scaleY(3) translateX(-9em) translateY(-0.5em)');
$('.bird_body .deco_2').css('transform',
'rotate(0deg) scaleY(3) translateX(-3.5em) translateY(-2.5em)');
$('.bird_body .deco_3').css('transform', 'rotate(-10deg) scaleY(2)');
$('.bird_body .deco_4').css('transform', 'rotate(-10deg) scaleY(2)');
};
function decorationMainColor(color,code) {
$('.deco_3, .deco_4').css('background', '#' + color)
$('#ateyestext').html('Code: '+ code)
$('#dnaDecorationAtEye').html(code)
};
function middleColor(color,code) {
$('.deco_2').css('background', '#' + color)
$('#middletext').html('Code: '+ code)
$('#dnaDecorationMid').html(code)
};
function smallColor(color,code) {
$('.deco_1').css('background', '#' + color)
$('#smalltext').html('Code: '+ code)
$('#dnaDecorationSmall').html(code)
};
function animationVariation(num) {
$('#dnaAnimation').html(num)
switch (num) {
case 0:
resetAnimation();
$('#animationtext').html('None');
break;
case 1:
resetAnimation();
$('#animationtext').html('Kick');
animationType1();
break;
case 2:
resetAnimation();
$('#animationtext').html('Float');
animationType2();
break;
case 3:
resetAnimation();
$('#animationtext').html('Compress');
animationType3();
break;
case 4:
resetAnimation();
$('#animationtext').html('Speak');
animationType4();
break;
case 5:
resetAnimation();
$('#animationtext').html('Wag');
animationType5();
break;
case 6:
resetAnimation();
$('#animationtext').html('Attention');
animationType6();
break;
case 7:
resetAnimation();
$('#animationtext').html('Combi');
animationType7();
break;
case 8:
resetAnimation();
$('#animationtext').html('Follow');
animationType8();
break;
default:
resetAnimation();
$('#animationtext').html('None');
};
};
function resetAnimation() {
$('*').removeClass('slowRotateBird floatingBird compressingBird upperSpeakingBird');
$('*').removeClass('lowerSpeakingBird topWaggingTail middleWaggingTail');
$('*').removeClass('bottomWaggingTail topAttention bottomAttention');
document.onmousemove = function(){};
};
function animationType1() {
$('.bird').addClass('slowRotateBird');
};
function animationType2() {
$('.bird').addClass('floatingBird');
};
function animationType3() {
$('.bird').addClass('compressingBird');
};
function animationType4() {
$('.beak_upper').addClass('upperSpeakingBird');
$('.beak_lower').addClass('lowerSpeakingBird');
};
function animationType5() {
$('.tail_top').addClass('topWaggingTail');
$('.tail_middle').addClass('middleWaggingTail');
$('.tail_bottom').addClass('bottomWaggingTail');
};
function animationType6() {
$('.feather_top').addClass('topAttention');
$('.feather_bottom').addClass('bottomAttention');
};
function animationType7() {
$('.bird').addClass('floatingBird');
$('.beak_upper').addClass('upperSpeakingBird');
$('.beak_lower').addClass('lowerSpeakingBird');
$('.tail_top').addClass('topWaggingTail');
$('.tail_middle').addClass('middleWaggingTail');
$('.tail_bottom').addClass('bottomWaggingTail');
$('.feather_top').addClass('topAttention');
$('.feather_bottom').addClass('bottomAttention');
};
function animationType8() {
basicEyes();
var eyeballs = document.getElementsByClassName("pupil");
document.onmousemove = function(event) {
var x = event.clientX * 65 / window.innerWidth + "%";
var y = event.clientY * 65 / window.innerHeight + "%";
for (let i = 0; i < eyeballs.length; i++) {
eyeballs[i].style.left = x;
eyeballs[i].style.top = y;
};
};
};

57
client/assets/js/web3.min.js vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

113
client/breeding.html Normal file
View File

@ -0,0 +1,113 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Breeding - Angry Birds on the Block</title>
<link rel="apple-touch-icon" type="image/png" sizes="180x180"
href="assets/media/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32"
href="assets/media/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16"
href="assets/media/favicons/favicon-16x16.png">
<link rel="manifest" href="assets/media/favicons/site.webmanifest">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/animations.css">
<link rel="stylesheet" href="assets/css/bird.css">
<link rel="stylesheet" href="assets/css/styles.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins&display=swap">
<script type="text/javascript" src="assets/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript" src="assets/js/web3.min.js"></script>
<script type="text/javascript" src="assets/js/abi.js"></script>
<script type="text/javascript" src="assets/bootstrap/js/popper.js"></script>
<script type="text/javascript" src="assets/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container p-5">
<!-- Navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#"><img id="logo" height="50"
src="assets/media/Birdy.jpg"> Crypto Birdies </a>
<button class="navbar-toggler" type="button" data-toggle="collapse"
data-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarTogglerDemo02">
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
<li class="nav-item">
<a class="nav-link" href="./index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./catalog.html">Catalog</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./breeding.html">Breeding</a>
</li>
<li id="designStudio" class="nav-item">
<a class="nav-link" href="./studio.html">Design Studio</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./market.html">Market Place</a>
</li>
</ul>
</div>
<!-- Allows owner to pause execution of buyBird() and withdrawFunds() for maintenance only -->
<button style="display: none" id="pauseButton" class="btn btn-danger my-2 my-sm-0" type="submit"></button>
</nav><br>
<!-- Headlines -->
<div align="center">
<div style="display: none" class="alert alert-danger" role="alert" id="pauseMessage">
Contract paused for maintenance! Buying birds and withdrawing funds is temporarily unavailable.
Normal operations will be restored as soon as possible! Please check in soon!
</div>
<h1 class="c-white"><b>Breed your own birdies!</b></h1>
<p id="insufficient" class="c-white">Choose the parents for your birdy once you own at least two adults</p>
<div class="alert alert-success" role="alert" id="birdCreation"
style="display: none"></div><br>
</div><br>
<!-- Parents, Child & Buttons -->
<div id="dameDisplay"></div>
<div id="sireDisplay"></div>
<div id="childDisplay">
<img style ="display: none" class="evolvingHeart" src="assets/media/Hearts.png">
</div>
<button id="dameButton" type="button" class="btn btn-primary">Change Dame</button>
<button id="sireButton" type="button" class="btn btn-primary">Change Sire</button>
<button id="breedButton" type="button" class="btn btn-danger">Breed a new bird!</button>
<button id="breedAgainButton" type="button" class="btn btn-danger">Breed again!</button>
<button id="swapButton" type="button" class="btn btn-primary"
style="display: none">Swap Dame and Sire</button><br>
<!-- Modal box -->
<div class="modal" id="birdSelection" tabindex="-1" role="dialog">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">My birds</h5>
</div>
<div class="modal-body">
<p>Select one of your birds.</p>
<div class="row"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
<!-- Footer -->
<footer align="center" id="breedFooter">
Written by <a href="mailto:the.rainmaker@mail.com">The Rainmaker</a>
</footer>
</div>
</body>
<script src="assets/js/blockchain.js"></script>
<script src="assets/js/colors.js"></script>
<script src="assets/js/breeding.js"></script>
<script src="assets/js/rendering.js"></script>
</html>

93
client/catalog.html Normal file
View File

@ -0,0 +1,93 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Catalog - Angry Birds on the Block</title>
<link rel="apple-touch-icon" type="image/png" sizes="180x180"
href="assets/media/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32"
href="assets/media/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16"
href="assets/media/favicons/favicon-16x16.png">
<link rel="manifest" href="assets/media/favicons/site.webmanifest">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/animations.css">
<link rel="stylesheet" href="assets/css/bird.css">
<link rel="stylesheet" href="assets/css/styles.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins&display=swap">
<script type="text/javascript" src="assets/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript" src="assets/js/web3.min.js"></script>
<script type="text/javascript" src="assets/js/abi.js"></script>
<script type="text/javascript" src="assets/bootstrap/js/popper.js"></script>
<script type="text/javascript" src="assets/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container p-5">
<!-- Navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#"><img id="logo" height="50"
src="assets/media/Birdy.jpg"> Crypto Birdies </a>
<button class="navbar-toggler" type="button" data-toggle="collapse"
data-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarTogglerDemo02">
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
<li class="nav-item">
<a class="nav-link" href="./index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./catalog.html">Catalog</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./breeding.html">Breeding</a>
</li>
<li id="designStudio" class="nav-item">
<a class="nav-link" href="./studio.html">Design Studio</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./market.html">Market Place</a>
</li>
</ul>
</div>
<!-- Allows owner to pause execution of buyBird() and withdrawFunds() for maintenance only -->
<button style="display: none" id="pauseButton" class="btn btn-danger my-2 my-sm-0" type="submit"></button>
</nav><br>
<!-- Headlines & Receipt -->
<div align="center">
<div style="display: none" class="alert alert-danger" role="alert" id="pauseMessage">
Contract paused for maintenance! Buying birds and withdrawing funds is temporarily unavailable.
Normal operations will be restored as soon as possible! Please check in soon!
</div>
<h1 class="c-white"><b>My Bird Collection</b></h1>
<p>Once you own birds, they will be displayed here</p>
<p>Make money by creating offers for your birds! -
Active offers will be transferred to the Market Place</p>
<div id="withdrawBox" class="alert alert-success" role="alert">
<span id="fundsAvailable"></span>
<button id="withdrawButton" class="btn btn-success" type="button"
id="button-addon2">Withdraw All
</button>
</div>
<div class="alert alert-success" role="alert" id="offerCreated"
style="display: none"></div>
</div>
<!-- Bird Boxes -->
<div class="row"></div>
<!-- Footer -->
<footer align="center">
Written by <a href="mailto:the.rainmaker@mail.com">The Rainmaker</a>
</footer>
</div>
</body>
<script src="assets/js/blockchain.js"></script>
<script src="assets/js/colors.js"></script>
<script src="assets/js/rendering.js"></script>
<script src="assets/js/catalog.js"></script>
</html>

107
client/index.html Normal file
View File

@ -0,0 +1,107 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Crypto Birdies</title>
<link rel="apple-touch-icon" type="image/png" sizes="180x180"
href="assets/media/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32"
href="assets/media/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16"
href="assets/media/favicons/favicon-16x16.png">
<link rel="manifest" href="assets/media/favicons/site.webmanifest">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/styles.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins&display=swap">
<script type="text/javascript" src="assets/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript" src="assets/js/web3.min.js"></script>
<script type="text/javascript" src="assets/js/abi.js"></script>
<script type="text/javascript" src="assets/bootstrap/js/popper.js"></script>
<script type="text/javascript" src="assets/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container p-5">
<!-- Navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#"><img id="logo" height="50"
src="assets/media/Birdy.jpg"> Crypto Birdies </a>
<button class="navbar-toggler" type="button" data-toggle="collapse"
data-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarTogglerDemo02">
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
<li class="nav-item">
<a class="nav-link" href="./index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./catalog.html">Catalog</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./breeding.html">Breeding</a>
</li>
<li id="designStudio" class="nav-item">
<a class="nav-link" href="./studio.html">Design Studio</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./market.html">Market Place</a>
</li>
</ul>
</div>
<!-- Allows owner to pause execution of buyBird() and withdrawFunds() for maintenance only -->
<button style="display: none" id="pauseButton" class="btn btn-danger my-2 my-sm-0" type="submit"></button>
</nav><br>
<!-- Feature Cards -->
<div style="display: none" class="alert alert-danger" role="alert" id="pauseMessage">
Contract paused for maintenance! Buying birds and withdrawing funds is temporarily unavailable.
Normal operations will be restored as soon as possible! Please check in soon!
</div>
<div class="card-deck">
<div class="card">
<img src="assets/media/Bird.jpg" class="card-img-top" alt="collections">
<div class="card-body card-special">
<h5 class="card-title">Collect & earn rewards</h5>
<p class="card-text">Collect all types of birds with unique attributes!
Earn special birds through breeding.</p>
</div>
</div>
<div class="card">
<img src="assets/media/Breed.gif" class="card-img-top" alt="breeding">
<div class="card-body card-special">
<h5 class="card-title">Breed adorable birds & unlock uncommon traits</h5>
<p class="card-text">Create new birds by pairing two parents.
Fuse them to get the rarest birds!</p>
</div>
</div>
<div class="card">
<img src="assets/media/Coins.png" class="card-img-top" alt="crypto-currency">
<div class="card-body card-special">
<h5 class="card-title">Trade Birds</h5>
<p class="card-text">Buy or sell birds in a market place using crypto currency!
You can find the most exotic specimens here.</p>
</div>
</div>
</div><br>
<!-- Action Card -->
<div topCard class="card border-dark mb-3 justify-content-center topCard"
style="max-width: 18rem;">
<div class="card-body text-success">
<h5 id="cardTitle">Collect! Breed! Trade!</h5>
<button id="cardButton" class="btn btn-dark my-2 my-sm-0" type="submit"
onclick="window.location.href='./market.html';">Get your own Birds</button>
</div>
</div>
<footer align="center">
Written by <a href="mailto:the.rainmaker@mail.com">The Rainmaker</a>
</footer>
</div>
</body>
<script src="assets/js/blockchain.js"></script>
<script src="assets/js/index.js"></script>
</html>

95
client/market.html Normal file
View File

@ -0,0 +1,95 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Market Place - Angry Birds on the Block</title>
<link rel="apple-touch-icon" type="image/png" sizes="180x180"
href="assets/media/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32"
href="assets/media/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16"
href="assets/media/favicons/favicon-16x16.png">
<link rel="manifest" href="assets/media/favicons/site.webmanifest">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/animations.css">
<link rel="stylesheet" href="assets/css/bird.css">
<link rel="stylesheet" href="assets/css/styles.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins&display=swap">
<script type="text/javascript" src="assets/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript" src="assets/js/web3.min.js"></script>
<script type="text/javascript" src="assets/js/abi.js"></script>
<script type="text/javascript" src="assets/bootstrap/js/popper.js"></script>
<script type="text/javascript" src="assets/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container p-5">
<!-- Navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#"><img id="logo" height="50"
src="assets/media/Birdy.jpg"> Crypto Birdies </a>
<button class="navbar-toggler" type="button" data-toggle="collapse"
data-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarTogglerDemo02">
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
<li class="nav-item">
<a class="nav-link" href="./index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./catalog.html">Catalog</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./breeding.html">Breeding</a>
</li>
<li id="designStudio" class="nav-item">
<a class="nav-link" href="./studio.html">Design Studio</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./market.html">Market Place</a>
</li>
</ul>
</div>
<!-- Allows owner to pause execution of buyBird() and withdrawFunds() for maintenance only -->
<button style="display: none" id="pauseButton" class="btn btn-danger my-2 my-sm-0" type="submit"></button>
</nav><br>
<!-- Headlines & Receipt -->
<div align="center">
<div style="display: none" class="alert alert-danger" role="alert" id="pauseMessage">
Contract paused for maintenance! Buying birds and withdrawing funds is temporarily unavailable.
Normal operations will be restored as soon as possible! Please check in soon!
</div>
<h1 class="c-white"><b>My Offers</b></h1>
<p class="c-white">Cancelling an offer will return the bird to your catalog</p>
<div class="alert alert-success" role="alert" id="offerRemoved"
style="display: none"></div>
</div>
<!-- Offer Boxes -->
<div class="myOffers"></div><hr>
<!-- Headlines & Receipt -->
<div align="center">
<h1 class="c-white"><b>Offers of other Players</b></h1>
<p class="c-white">Buy Rare and Unusual Birds!</p>
<div class="alert alert-success" role="alert" id="birdPurchased"
style="display: none"></div>
</div>
<!-- Market Boxes -->
<div class="marketOffers"></div>
<!-- Footer -->
<footer align="center">
Written by <a href="mailto:the.rainmaker@mail.com">The Rainmaker</a>
</footer>
</div>
</body>
<script src="assets/js/blockchain.js"></script>
<script src="assets/js/colors.js"></script>
<script src="assets/js/rendering.js"></script>
<script src="assets/js/market.js"></script>
</html>

214
client/studio.html Normal file
View File

@ -0,0 +1,214 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Design Studio - Angry Birds on the Block</title>
<link rel="apple-touch-icon" type="image/png" sizes="180x180"
href="assets/media/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32"
href="assets/media/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16"
href="assets/media/favicons/favicon-16x16.png">
<link rel="manifest" href="assets/media/favicons/site.webmanifest">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/animations.css">
<link rel="stylesheet" href="assets/css/bird.css">
<link rel="stylesheet" href="assets/css/styles.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins&display=swap">
<script type="text/javascript" src="assets/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript" src="assets/js/web3.min.js"></script>
<script type="text/javascript" src="assets/js/abi.js"></script>
<script type="text/javascript" src="assets/bootstrap/js/popper.js"></script>
<script type="text/javascript" src="assets/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container p-5">
<!-- Navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#"><img id="logo" height="50"
src="assets/media/Birdy.jpg"> Crypto Birdies </a>
<button class="navbar-toggler" type="button" data-toggle="collapse"
data-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarTogglerDemo02">
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
<li class="nav-item">
<a class="nav-link" href="./index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./catalog.html">Catalog</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./breeding.html">Breeding</a>
</li>
<li id="designStudio" class="nav-item">
<a class="nav-link" href="#">Design Studio</a>
</li>
<li class="nav-item">
<a class="nav-link" href="./market.html">Market Place</a>
</li>
</ul>
</div>
<!-- Allows owner to pause execution of buyBird() and withdrawFunds() for maintenance only -->
<button style="display: none" id="pauseButton" class="btn btn-danger my-2 my-sm-0" type="submit"></button>
</nav><br>
<!-- Headlines -->
<div align="center">
<div style="display: none" class="alert alert-danger" role="alert" id="pauseMessage">
Contract paused for maintenance! Buying birds and withdrawing funds is temporarily unavailable.
Normal operations will be restored as soon as possible! Please check in soon!
</div>
<h1 class="c-white"><b>Design Studio</b></h1>
<p class="c-white">Create Your Own Bird</p>
<div class="alert alert-success" role="alert" id="birdCreation"
style="display: none"></div>
</div>
<!-- BirdBox -->
<div class="row">
<div class="col-lg-4 birdBox m-2 light-b-shadow">
<div class="bird">
<div class="tail">
<div class="tail_top"></div>
<div class="tail_middle"></div>
<div class="tail_bottom"></div>
</div>
<div class="feather">
<div class="feather_top"></div>
<div class="feather_bottom"></div>
</div>
<div class="bird_body">
<div class="bird_body bird_body_inner"></div>
<div class="deco_1"></div>
<div class="deco_2"></div>
<div class="deco_3"></div>
<div class="deco_4"></div>
</div>
<div class="belly"></div>
<div class="face">
<div class="eye eye_right">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="eye eye_left">
<div class="eyebrow"></div>
<div class="pupil"></div>
</div>
<div class="beak">
<div class="beak_upper"></div>
<div class="beak_lower"></div>
</div>
</div>
</div>
<br>
<div class="dnaDiv">
<b>
DNA:
<span id="dnaTopFeather"></span>
<span id="dnaBodyFeather"></span>
<span id="dnaTopBeak"></span>
<span id="dnaBottomBeak"></span>
<span id="dnaEyesShape"></span>
<span id="dnaDecorationPattern"></span>
<span id="dnaDecorationAtEye"></span>
<span id="dnaDecorationMid"></span>
<span id="dnaDecorationSmall"></span>
<span id="dnaAnimation"></span>
</b>
</div>
</div>
<!-- Color & Feature Box -->
<div class="col-lg-7 birdAttributes m-2 light-b-shadow ">
<button type="button" id="colorsButton"
class="m-2 btn btn-primary light-b-shadow"><b>Colors</b></button>
<button type="button" id="attributesButton"
class="m-2 btn btn-primary light-b-shadow"><b>Attributes</b></button>
<div class="form-group">
<div class="colorscreen"><br><br>
<label for="formControlRange"><b>Top Feathers</b>
<span class="badge badge-dark ml-2" id="topfeatherstext"></span></label>
<input type="range" min="10" max="99" class="form-control-range"
id="topfeatherscolor">
<label for="formControlRange"><b>Body Feathers</b><span
class="badge badge-dark ml-2" id="bodyfeatherstext"></span></label>
<input type="range" min="10" max="99" class="form-control-range"
id="bodyfeatherscolor">
<label for="formControlRange"><b>Beak - Top</b><span
class="badge badge-dark ml-2" id="topbeaktext"></span></label>
<input type="range" min="10" max="99" class="form-control-range"
id="topbeakcolor">
<label for="formControlRange"><b>Beak - Bottom</b><span
class="badge badge-dark ml-2" id="bottombeaktext"></span></label>
<input type="range" min="10" max="99" class="form-control-range"
id="bottombeakcolor">
</div>
<div class="attributes"><br>
<label for="formControlRange"><b>Eyes Shape</b><span
class="badge badge-dark ml-2" id="eyesshapetext"></span></label>
<input type="range" min="0" max="7" class="form-control-range"
id="eyesstyle">
<label for="formControlRange"><b>Decoration Pattern</b><span
class="badge badge-dark ml-2" id="decorationpatterntext"></span></label>
<input type="range" min="0" max="7" class="form-control-range"
id="decorationstyle">
<label for="formControlRange"><b>Decoration</b></label><br>
<div class="row">
<div class="col-md-4 mb-3">
<label for="formControlRange"><b>At Eyes</b>
<span class="badge badge-dark ml-2" id="ateyestext"></span></label>
<input type="range" min="10" max="99" class="form-control-range"
id="ateyescolor">
</div>
<div class="col-md-4 mb-3">
<label for="formControlRange"><b>Middle</b>
<span class="badge badge-dark ml-2" id="middletext"></span></label>
<input type="range" min="10" max="99" class="form-control-range"
id="middlecolor">
</div>
<div class="col-md-4 mb-3">
<label for="formControlRange"><b>Small</b>
<span class="badge badge-dark ml-2" id="smalltext"></span></label>
<input type="range" min="10" max="99" class="form-control-range"
id="smallcolor">
</div>
</div>
<label for="formControlRange"><b>Animation</b><span
class="badge badge-dark ml-2" id="animationtext"></span></label>
<input type="range" min="0" max="8" class="form-control-range"
id="animationstyle">
</div>
</div>
</div>
<div class="btn-group">
<div class="btn-group float-left">
<button type="button" id="randomizeButton"
class="btn btn-primary mr-5 tsp-1 m-1 light-b-shadow">
<b>Random Bird</b></button>
<button type="button" id="defaultButton"
class="btn btn-primary mr-5 tsp-1 m-1 light-b-shadow">
<b>Default Bird</b></button>
</div>
<div class="btn-group float-right">
<button type="button" id="createButton"
class="btn btn-success mr-5 tsp-1 m-1 light-b-shadow">
<b>Create Bird</b></button>
</div><br>
</div>
</div><br>
<footer align="center">
Written by <a href="mailto:the.rainmaker@mail.com">The Rainmaker</a>
</footer>
</div>
</body>
<script src="assets/js/blockchain.js"></script>
<script src="assets/js/colors.js"></script>
<script src="assets/js/studio.js"></script>
</html>

309
contracts/CryptoBirdies.sol Normal file
View File

@ -0,0 +1,309 @@
pragma solidity ^0.5.12;
import "./Ownable.sol";
import "./Destroyable.sol";
import "./IERC165.sol";
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./SafeMath.sol";
contract CryptoBirdies is Ownable, Destroyable, IERC165, IERC721 {
using SafeMath for uint256;
uint256 public constant maxGen0Birds = 10;//allow a maximum of 10 Gen0 birds
uint256 public gen0Counter = 0;
bytes4 internal constant _ERC721Checksum = bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));
//checksum used to determine if a receiving contract is able to handle ERC721 tokens
bytes4 private constant _InterfaceIdERC721 = 0x80ac58cd;
//checksum of function headers that are required in standard interface
bytes4 private constant _InterfaceIdERC165 = 0x01ffc9a7;
//checksum of function headers that are required in standard interface
string private _name;
string private _symbol;
struct Bird {
uint256 genes;
uint64 birthTime;
uint32 mumId;
uint32 dadId;
uint16 generation;
}
Bird[] birdies;
mapping(uint256 => address) public birdOwner;
mapping(address => uint256) ownsNumberOfTokens;
mapping(uint256 => address) public approvalOneBird;//which bird is approved to be transfered
//by an address other than the owner
mapping(address => mapping (address => bool)) private _operatorApprovals;
//approval to handle all tokens of an address by another
//_operatorApprovals[owneraddress][operatoraddress] = true/false;
//ERC721 events are not defined here as they are inherited from IERC721
event Birth(address owner, uint256 birdId, uint256 mumId, uint256 dadId, uint256 genes);
constructor(string memory name, string memory symbol) public {
_name = name;
_symbol = symbol;
_createBird(0, 0, 0, uint256(-1), address(0));
//Bird 0 doesn't do anything, but it exists in the mappings and arrays to avoid issues in the market place
}
function getContractOwner() external view returns (address contractowner) {
return _owner;
}
function breed(uint256 _dadId, uint256 _mumId) external returns (uint256){
require(birdOwner[_dadId] == msg.sender && birdOwner[_mumId] == msg.sender,
"You can't breed what you don't own");
(uint256 _dadDna,,,, uint256 _dadGeneration) = getBird(_dadId);//discarding redundant data here
(uint256 _mumDna,,,, uint256 _mumGeneration) = getBird(_mumId);//discarding redundant data here
uint256 _newDna = _mixDna(
_dadDna,
_mumDna,
uint8(now % 255),//This will return a number 0-255. e.g. 10111000
uint8(now % 1),//seventeenth digit
uint8(now % 7),//number to select random pair.
uint8((now % 89) + 10)//value of random pair, making sure there's no leading '0'.
);
uint256 _newGeneration;
if (_dadGeneration <= _mumGeneration) {
_newGeneration = _dadGeneration;
} else {
_newGeneration = _mumGeneration;
}
_newGeneration = SafeMath.add(_newGeneration, 1);
return _createBird(_mumId, _dadId, _newGeneration, _newDna, msg.sender);
}
function supportsInterface(bytes4 _interfaceId) external view returns (bool) {
return (_interfaceId == _InterfaceIdERC721 || _interfaceId == _InterfaceIdERC165);
}
function createBirdGen0(uint256 genes) public onlyOwner returns (uint256) {
require(gen0Counter < maxGen0Birds, "Maximum number of Birds is reached. No new birds allowed!");
gen0Counter = SafeMath.add(gen0Counter, 1);
return _createBird(0, 0, 0, genes, msg.sender);
}
function _createBird(
uint256 _mumId,
uint256 _dadId,
uint256 _generation,
uint256 _genes,
address _owner
) internal returns (uint256) {
Bird memory _bird = Bird({
genes: _genes,
birthTime: uint64(now),
mumId: uint32(_mumId), //easier to input 256 and later convert to 32.
dadId: uint32(_dadId),
generation: uint16(_generation)
});
birdies.push(_bird);
uint256 newBirdId = SafeMath.sub(birdies.length, 1);//want to start with zero.
_transfer(address(0), _owner, newBirdId);//transfer from nowhere. Creation event.
emit Birth(_owner, newBirdId, _mumId, _dadId, _genes);
return newBirdId;
}
function getBird(uint256 tokenId) public view returns (
uint256 genes,
uint256 birthTime,
uint256 mumId,
uint256 dadId,
uint256 generation) //code looks cleaner when the params appear here vs. in the return statement.
{
require(tokenId < birdies.length, "Token ID doesn't exist.");
Bird storage bird = birdies[tokenId];//saves space over using memory, which would make a copy
genes = bird.genes;
birthTime = uint256(bird.birthTime);
mumId = uint256(bird.mumId);
dadId = uint256(bird.dadId);
generation = uint256(bird.generation);
}
function getAllBirdsOfOwner(address owner) external view returns(uint256[] memory) {
uint256[] memory allBirdsOfOwner = new uint[](ownsNumberOfTokens[owner]);
uint256 j = 0;
for (uint256 i = 0; i < birdies.length; i++) {
if (birdOwner[i] == owner) {
allBirdsOfOwner[j] = i;
j = SafeMath.add(j, 1);
}
}
return allBirdsOfOwner;
}
function balanceOf(address owner) external view returns (uint256 balance) {
return ownsNumberOfTokens[owner];
}
function totalSupply() external view returns (uint256 total) {
return birdies.length;
}
function name() external view returns (string memory tokenName){
return _name;
}
function symbol() external view returns (string memory tokenSymbol){
return _symbol;
}
function ownerOf(uint256 tokenId) external view returns (address owner) {
require(tokenId < birdies.length, "Token ID doesn't exist.");
return birdOwner[tokenId];
}
function transfer(address to, uint256 tokenId) external {
require(to != address(0), "Use the burn function to burn tokens!");
require(to != address(this), "Wrong address, try again!");
require(birdOwner[tokenId] == msg.sender);
_transfer(msg.sender, to, tokenId);
}
function _transfer(address _from, address _to, uint256 _tokenId) internal {
require(_to != address(this));
ownsNumberOfTokens[_to] = SafeMath.add(ownsNumberOfTokens[_to], 1);
birdOwner[_tokenId] = _to;
if (_from != address(0)) {
ownsNumberOfTokens[_from] = SafeMath.sub(ownsNumberOfTokens[_from], 1);
delete approvalOneBird[_tokenId];//when owner changes, approval must be removed.
}
emit Transfer(_from, _to, _tokenId);
}
function approve(address _approved, uint256 _tokenId) external {
require(birdOwner[_tokenId] == msg.sender || _operatorApprovals[birdOwner[_tokenId]][msg.sender] == true,
"You are not authorized to access this function.");
approvalOneBird[_tokenId] = _approved;
emit Approval(msg.sender, _approved, _tokenId);
}
function setApprovalForAll(address _operator, bool _approved) external {
require(_operator != msg.sender);
_operatorApprovals[msg.sender][_operator] = _approved;
emit ApprovalForAll(msg.sender, _operator, _approved);
}
function getApproved(uint256 _tokenId) external view returns (address) {
require(_tokenId < birdies.length, "Token doesn't exist");
return approvalOneBird[_tokenId];
}
function isApprovedForAll(address _owner, address _operator) external view returns (bool) {
return _operatorApprovals[_owner][_operator];
}
function _safeTransfer(address _from, address _to, uint256 _tokenId, bytes memory _data) internal {
require(_checkERC721Support(_from, _to, _tokenId, _data));
_transfer(_from, _to, _tokenId);
}
function _checkERC721Support(address _from, address _to, uint256 _tokenId, bytes memory _data)
internal returns(bool) {
if(!_isContract(_to)) {
return true;
}
bytes4 returnData = IERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data);
//Call onERC721Received in the _to contract
return returnData == _ERC721Checksum;
//Check return value
}
function _isContract(address _to) internal view returns (bool) {
uint32 size;
assembly{
size := extcodesize(_to)
}
return size > 0;
//check if code size > 0; wallets have 0 size.
}
function _isOwnerOrApproved(address _from, address _to, uint256 _tokenId) internal view returns (bool) {
require(_from == msg.sender ||
approvalOneBird[_tokenId] == msg.sender ||
_operatorApprovals[_from][msg.sender],
"You are not authorized to use this function");
require(birdOwner[_tokenId] == _from, "Owner incorrect");
require(_to != address(0), "Error: Operation would delete this token permanently");
require(_tokenId < birdies.length, "Token doesn't exist");
return true;
}
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external {
_isOwnerOrApproved(_from, _to, _tokenId);
_safeTransfer(_from, _to, _tokenId, data);
}
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external {
_isOwnerOrApproved(_from, _to, _tokenId);
_safeTransfer(_from, _to, _tokenId, "");
}
function transferFrom(address _from, address _to, uint256 _tokenId) external {
_isOwnerOrApproved(_from, _to, _tokenId);
_transfer(_from, _to, _tokenId);
}
function _mixDna(
uint256 _dadDna,
uint256 _mumDna,
uint8 random,
uint8 randomSeventeenthDigit,
uint8 randomPair,
uint8 randomNumberForRandomPair
) internal pure returns (uint256){
uint256[9] memory geneArray;
uint256 i;
uint256 counter = 7; // start on the right end
//DNA example: 11 22 33 44 55 66 77 88 9
if(randomSeventeenthDigit == 0){
geneArray[8] = uint8(_mumDna % 10); //this takes the 17th gene from mum.
} else {
geneArray[8] = uint8(_dadDna % 10); //this takes the 17th gene from dad.
}
_mumDna = SafeMath.div(_mumDna, 10); // division by 10 removes the last digit
_dadDna = SafeMath.div(_dadDna, 10); // division by 10 removes the last digit
for (i = 1; i <= 128; i=i*2) { //1, 2 , 4, 8, 16, 32, 64 ,128
if(random & i == 0){ //00000001
geneArray[counter] = uint8(_mumDna % 100); //00000010 etc.
} else { //11001011 &
geneArray[counter] = uint8(_dadDna % 100); //00000001 will go through random number bitwise
} //if(1) - dad gene
_mumDna = SafeMath.div(_mumDna, 100); //if(0) - mum gene
_dadDna = SafeMath.div(_dadDna, 100); //division by 100 removes last two digits from genes
if(counter > 0) {
counter = SafeMath.sub(counter, 1);
}
}
geneArray[randomPair] = randomNumberForRandomPair; //extra randomness for random pair.
uint256 newGene = 0;
//geneArray example: [11, 22, 33, 44, 55, 66, 77, 88, 9]
for (i = 0; i < 8; i++) { //8 is number of pairs in array
newGene = SafeMath.mul(newGene, 100); //adds two digits to newGene; no digits the first time
newGene = SafeMath.add(newGene, geneArray[i]); //adds a pair of genes
}
newGene = SafeMath.mul(newGene, 10); //add seventeenth digit
newGene = SafeMath.add(newGene, geneArray[8]);
return newGene;
}
}

10
contracts/Destroyable.sol Normal file
View File

@ -0,0 +1,10 @@
pragma solidity ^0.5.12;
import "./Ownable.sol";
contract Destroyable is Ownable{
function close() public onlyOwner {
selfdestruct(_owner);
}
}

24
contracts/IERC165.sol Normal file
View File

@ -0,0 +1,24 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.5.12;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

125
contracts/IERC721.sol Normal file
View File

@ -0,0 +1,125 @@
pragma solidity ^0.5.0;
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 {
/**
* @dev Emitted when `tokenId` token is transfered from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/*
* @dev Returns the total number of tokens in circulation.
*/
function totalSupply() external view returns (uint256 total);
/*
* @dev Returns the name of the token.
*/
function name() external view returns (string memory tokenName);
/*
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory tokenSymbol);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/* @dev Transfers `tokenId` token from `msg.sender` to `to`.
*
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `to` can not be the contract address.
* - `tokenId` token must be owned by `msg.sender`.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 tokenId) external;
/// @notice Change or reaffirm the approved address for an NFT
/// @dev The zero address indicates there is no approved address.
/// Throws unless `msg.sender` is the current NFT owner, or an authorized
/// operator of the current owner.
/// @param _approved The new approved NFT controller
/// @param _tokenId The NFT to approve
function approve(address _approved, uint256 _tokenId) external;
/// @notice Enable or disable approval for a third party ("operator") to manage
/// all of `msg.sender`'s assets
/// @dev Emits the ApprovalForAll event. The contract MUST allow
/// multiple operators per owner.
/// @param _operator Address to add to the set of authorized operators
/// @param _approved True if the operator is approved, false to revoke approval
function setApprovalForAll(address _operator, bool _approved) external;
/// @notice Get the approved address for a single NFT
/// @dev Throws if `_tokenId` is not a valid NFT.
/// @param _tokenId The NFT to find the approved address for
/// @return The approved address for this NFT, or the zero address if there is none
function getApproved(uint256 _tokenId) external view returns (address);
/// @notice Query if an address is an authorized operator for another address
/// @param _owner The address that owns the NFTs
/// @param _operator The address that acts on behalf of the owner
/// @return True if `_operator` is an approved operator for `_owner`, false otherwise
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
/// @notice Transfers the ownership of an NFT from one address to another address
/// @dev Throws unless `msg.sender` is the current owner, an authorized
/// operator, or the approved address for this NFT. Throws if `_from` is
/// not the current owner. Throws if `_to` is the zero address. Throws if
/// `_tokenId` is not a valid NFT. When transfer is complete, this function
/// checks if `_to` is a smart contract (code size > 0). If so, it calls
/// `onERC721Received` on `_to` and throws if the return value is not
/// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
/// @param data Additional data with no specified format, sent in call to `_to`
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external;
/// @notice Transfers the ownership of an NFT from one address to another address
/// @dev This works identically to the other function with an extra data parameter,
/// except this function just sets data to "".
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external;
/// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
/// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
/// THEY MAY BE PERMANENTLY LOST
/// @dev Throws unless `msg.sender` is the current owner, an authorized
/// operator, or the approved address for this NFT. Throws if `_from` is
/// not the current owner. Throws if `_to` is the zero address. Throws if
/// `_tokenId` is not a valid NFT.
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
function transferFrom(address _from, address _to, uint256 _tokenId) external;
}

View File

@ -0,0 +1,5 @@
pragma solidity ^0.5.12;
interface IERC721Receiver {
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}

View File

@ -0,0 +1,82 @@
pragma solidity ^0.5.12;
import "./CryptoBirdies.sol";
import "./Ownable.sol";
/*
* Market place to trade birds (should **in theory** be used for any ERC721 token)
* It needs an existing bird contract to interact with
* Note: it does not inherit from the contract
* Note: It takes ownership of the bird for the duration that is is on the marketplace.
*/
interface IMarketPlace {
event MarketTransaction(string TxType, address owner, uint256 tokenId);
event MonetaryTransaction(string message, address recipient, uint256 amount);
/**
* Set the current contract address and initialize the instance of the contract.
* Requirement: Only the contract owner can call.
*/
function setContract(address _contractAddress) external;
/**
* Sets status of _paused to true which affects all functions that have whenNotPaused modifiers.
*/
function pause() external;
/**
* Sets status of _paused to false which affects all functions that have whenNotPaused modifiers.
*/
function resume() external;
/**
* Get the details about a offer for _tokenId. Throws an error if there is no active offer for _tokenId.
*/
function getOffer(uint256 _tokenId) external view returns (address seller, uint256 price, uint256 index, uint256 tokenId, bool active);
/**
* Get all tokenId's that are currently for sale. Returns an empty array if no offer exists.
*/
function getAllTokensOnSale() external view returns (uint256[] memory listOfOffers);
/**
* Creates a new offer for _tokenId for the price _price.
* Emits the MarketTransaction event with txType "Create offer"
* Requirement: Only the owner of _tokenId can create an offer.
* Requirement: There can only be one active offer for a token at a time.
* Requirement: Marketplace contract (this) needs to be an approved operator when the offer is created.
*/
function setOffer(uint256 _price, uint256 _tokenId) external;
/**
* Removes an existing offer.
* Emits the MarketTransaction event with txType "Remove offer"
* Requirement: Only the seller of _tokenId can remove an offer.
*/
function removeOffer(uint256 _tokenId) external;
/**
* Executes the purchase of _tokenId.
* Transfers the token using transferFrom in CryptoBirdies.
* Transfers funds to the _fundsToBeCollected mapping.
* Removes the offer from the mapping.
* Sets the offer in the array to inactive.
* Emits the MarketTransaction event with txType "Buy".
* Requirement: The msg.value needs to equal the price of _tokenId
* Requirement: There must be an active offer for _tokenId
*/
function buyBird(uint256 _tokenId) external payable;
/**
* Returns current balance of msg.sender
*/
function getBalance() external view returns (uint256);
/**
* Send funds to msg.sender.
* Emits a MonetaryTransaction event "Successful Transfer".
* Requirement: msg.sender must have funds in the mapping.
*/
function withdrawFunds() external payable;
}

193
contracts/Marketplace.sol Normal file
View File

@ -0,0 +1,193 @@
pragma solidity ^0.5.12;
import "./CryptoBirdies.sol";
import "./Ownable.sol";
import "./IMarketplace.sol";
import "./SafeMath.sol";
/*
* Market place to trade birds (should **in theory** be used for any ERC721 token)
* It needs an existing bird contract to interact with
* Note: it does not inherit from the contract
* Note: It takes ownership of the bird for the duration that is is on the marketplace.
*/
contract MarketPlace is Ownable, IMarketPlace {
CryptoBirdies private _cryptoBirdies;
using SafeMath for uint256;
struct Offer {
address payable seller;
uint256 price;
uint256 index;
uint256 tokenId;
bool active;
}
bool internal _paused;
Offer[] offers;
mapping(uint256 => Offer) tokenIdToOffer;
mapping(address => uint256) internal _fundsToBeCollected;
//Contract has one event that is already declared in the interface.
//Contract can be paused by owner to ensure bugs can be fixed after deployment
modifier whenNotPaused() {
require(!_paused);
_;
}
modifier whenPaused() {
require(_paused);
_;
}
function setContract(address _contractAddress) onlyOwner public {
_cryptoBirdies = CryptoBirdies(_contractAddress);
}
constructor(address _contractAddress) public {
setContract(_contractAddress);
_paused = false;
}
function pause() public onlyOwner whenNotPaused {
_paused = true;
}
function resume() public onlyOwner whenPaused {
_paused = false;
}
function isPaused() public view returns (bool) {
return _paused;
}
function getOffer(uint256 _tokenId) public view returns (
address seller,
uint256 price,
uint256 index,
uint256 tokenId,
bool active) {
require(tokenIdToOffer[_tokenId].active == true, "No active offer at this time");
return (tokenIdToOffer[_tokenId].seller,
tokenIdToOffer[_tokenId].price,
tokenIdToOffer[_tokenId].index,
tokenIdToOffer[_tokenId].tokenId,
tokenIdToOffer[_tokenId].active);
}
function getAllTokensOnSale() public view returns (uint256[] memory listOfOffers) {
uint256 resultId = 0;//index for all birds with active offer status (true)
for (uint256 index = 0; index < offers.length; index++) {
if (offers[index].active == true) {
resultId = SafeMath.add(resultId, 1);//determine length of array to return
}
}
if (offers.length == 0) {
return new uint256[](0);//returns empty array
} else {
uint256[] memory allTokensOnSale = new uint256[](resultId);
//initialize new array with correct length
resultId = 0;//reset index of new array
for (uint256 index = 0; index < offers.length; index++) {//iterate through entire offers array
if (offers[index].active == true) {
allTokensOnSale[resultId] = offers[index].tokenId;
resultId = SafeMath.add(resultId, 1);
}
}
return allTokensOnSale;
}
}
function _ownsBird(address _address, uint256 _tokenId) internal view returns (bool) {
return (_cryptoBirdies.ownerOf(_tokenId) == _address);
}
function setOffer(uint256 _price, uint256 _tokenId) public {
require(_ownsBird(msg.sender, _tokenId),
"Only the owner of the bird can initialize an offer");
require(tokenIdToOffer[_tokenId].active == false,
"You already created an offer for this bird. Please remove it first before creating a new one.");
require(_cryptoBirdies.isApprovedForAll(msg.sender, address(this)),
"MarketPlace contract must first be an approved operator for your birds");
Offer memory _currentOffer = Offer({//set offer
seller: msg.sender,
price: _price,
index: offers.length,
tokenId: _tokenId,
active: true
});
tokenIdToOffer[_tokenId] = _currentOffer;//update mapping
offers.push(_currentOffer);//update array
emit MarketTransaction("Offer created", msg.sender, _tokenId);
}
function removeOffer(uint256 _tokenId) public {
require(tokenIdToOffer[_tokenId].seller == msg.sender,
"Only the owner of the bird can withdraw the offer.");
offers[tokenIdToOffer[_tokenId].index].active = false;
//don't iterate through array, simply set active to false.
delete tokenIdToOffer[_tokenId];//delete entry in mapping
emit MarketTransaction("Offer removed", msg.sender, _tokenId);
}
function buyBird(uint256 _tokenId) public payable whenNotPaused{
Offer memory _currentOffer = tokenIdToOffer[_tokenId];
//checks
require(_currentOffer.active, "There is no active offer for this bird");
require(msg.value == _currentOffer.price, "The amount offered is not equal to the requested amount");
//effects
delete tokenIdToOffer[_tokenId];//delete entry in mapping
offers[_currentOffer.index].active = false;//don't iterate through array, but simply set active to false.
//interactions
if (_currentOffer.price > 0) {
_fundsToBeCollected[_currentOffer.seller] =
SafeMath.add(_fundsToBeCollected[_currentOffer.seller], _currentOffer.price);
//instead of sending money to seller it is deposited in a mapping waiting for seller to pull.
}
_cryptoBirdies.transferFrom(_currentOffer.seller, msg.sender, _tokenId);//ERC721 ownership transferred
emit MarketTransaction("Bird successfully purchased", msg.sender, _tokenId);
}
function getBalance() public view returns (uint256) {
return _fundsToBeCollected[msg.sender];
}
function withdrawFunds() public payable whenNotPaused{
//check
require(_fundsToBeCollected[msg.sender] > 0, "No funds available at this time");
uint256 toWithdraw = _fundsToBeCollected[msg.sender];
//effect
_fundsToBeCollected[msg.sender] = 0;
//interaction
msg.sender.transfer(toWithdraw);
//making sure transfer executed correctly
assert(_fundsToBeCollected[msg.sender] == 0);
//emit event
emit MonetaryTransaction("Funds successfully received", msg.sender, toWithdraw);
}
}

19
contracts/Migrations.sol Normal file
View File

@ -0,0 +1,19 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.8.0;
contract Migrations {
address public _owner = msg.sender;
uint public _last_completed_migration;
modifier restricted() {
require(
msg.sender == _owner,
"This function is restricted to the contract's owner"
);
_;
}
function setCompleted(uint _completed) public restricted {
_last_completed_migration = _completed;
}
}

16
contracts/Ownable.sol Normal file
View File

@ -0,0 +1,16 @@
pragma solidity ^0.5.12;
contract Ownable{
address payable internal _owner;
modifier onlyOwner(){
require(msg.sender == _owner,
"You need to be owner of the contract in order to access this functionality!");
_;
}
constructor() public{
_owner = msg.sender;
}
}

159
contracts/Safemath.sol Normal file
View File

@ -0,0 +1,159 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.5.12;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}

37
contracts/TestBirdies.sol Normal file
View File

@ -0,0 +1,37 @@
pragma solidity ^0.5.12;
import "./CryptoBirdies.sol";
contract TestBirdies is CryptoBirdies {
constructor(string memory name, string memory symbol) CryptoBirdies(name, symbol) public{}
function testCreateBird(uint256 genes, address owner) public returns (uint256) {
return _createBird(0, 0, 0, genes, owner);
}
function testCreateGenXBird(uint256 generation, uint256 genes, address owner) public returns (uint256) {
return _createBird(0, 0, generation, genes, owner);
}
function testMixDna(
uint256 _dadDna,
uint256 _mumDna,
uint8 random,
uint8 randomSeventeenthDigit,
uint8 randomPair,
uint8 randomNumberForRandomPair
) public pure returns (uint256){
return _mixDna(
_dadDna,
_mumDna,
random,
randomSeventeenthDigit,
randomPair,
randomNumberForRandomPair);
}
function testSetGenCounter(uint256 value) public returns (uint256){
return gen0Counter = value;
}
}

14
contracts/TestErc.sol Normal file
View File

@ -0,0 +1,14 @@
pragma solidity ^0.5.12;
import "./IERC721Receiver.sol";
contract TestErc is IERC721Receiver {
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4) {
operator;//mention parameters only to suppress warnings in truffle
from;
tokenId;
data;
return bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));
}
}

48
contracts/TestMarket.sol Normal file
View File

@ -0,0 +1,48 @@
pragma solidity ^0.5.12;
import "./Marketplace.sol";
contract TestMarket is MarketPlace {
constructor(address _contractAddress) MarketPlace(_contractAddress) public{}
function getOfferFromMapping(uint256 id) public view returns(
address seller,
uint256 price,
uint256 index,
uint256 tokenId,
bool active) {
return (tokenIdToOffer[id].seller,
tokenIdToOffer[id].price,
tokenIdToOffer[id].index,
tokenIdToOffer[id].tokenId,
tokenIdToOffer[id].active);
}
function getOfferFromArray(uint256 id) public view returns(
address seller,
uint256 price,
uint256 index,
uint256 tokenId,
bool active) {
return (offers[id].seller,
offers[id].price,
offers[id].index,
offers[id].tokenId,
offers[id].active);
}
function getBalanceOfMapping(address caller) public view returns(uint256 amount) {
return _fundsToBeCollected[caller];
}
function testSetBalance(uint256 amount) public payable {
_fundsToBeCollected[msg.sender] = amount;
}
function testSetPause() public onlyOwner {
_paused = true;
}
}

View File

@ -0,0 +1,5 @@
const Migrations = artifacts.require("Migrations");
module.exports = function(deployer) {
deployer.deploy(Migrations);
};

View File

@ -0,0 +1,9 @@
const ERC721 = artifacts.require("CryptoBirdies");
module.exports = async function(deployer) {
await deployer.deploy(ERC721, "CryptoBird", "CBX");
const instance = await ERC721.deployed();
if(instance) {
console.log("CryptoBirdies successfully deployed.")
}
}

View File

@ -0,0 +1,10 @@
const CryptoBirdies = artifacts.require("CryptoBirdies");
const MarketPlace = artifacts.require("MarketPlace");
module.exports = async function(deployer) {
await deployer.deploy(MarketPlace, CryptoBirdies.address);
const instance = await MarketPlace.deployed();
if(instance) {
console.log("MarketPlace successfully deployed.")
}
}

3825
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

31
package.json Normal file
View File

@ -0,0 +1,31 @@
{
"name": "crypto_birdies",
"version": "1.0.0",
"description": "This is a clone of the famous Crypto Kitties.\r For an idea how the game works, see here: https://guide.cryptokitties.co/guide/",
"main": "truffle-config.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/TobyKreiselmaier/Crypto-Birdies.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/TobyKreiselmaier/Crypto-Birdies/issues"
},
"homepage": "https://github.com/TobyKreiselmaier/Crypto-Birdies#readme",
"devDependencies": {
"chai": "^4.2.0",
"truffle-assertions": "^0.9.2"
},
"dependencies": {
"@truffle/hdwallet-provider": "^1.1.1",
"bip39": "^3.0.2",
"dotenv": "^8.2.0"
}
}

1247
test/Unit_Testing.js Normal file

File diff suppressed because it is too large Load Diff