Assignment - Breeding Frontend

hey @RichJamo ! Errors in line 72 if breedKitty. Please send me a picture where you defining this instance. Also you can pass it like an argument, but the problem here is that is not getting the instance variable.

This part was really difficult for me I took me so much time and efforts, so much google, and saw this forum, changes on files created before for the project (a lot of changes). I need to include Ids(on html) on my cats and make functions that works with Ids and not classes, change the default cat for working with id=ā€œ00ā€, a lot of new functions, I changed those functions with switch (I have so much problems I used instead IF)
I used only a page for catalog and breed

image
image
image

this is my code
Catalogue Html

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="../client/assets/js/jquery-3.4.1.js"></script>
        <link rel="stylesheet" href="../client/assets/bootstrap/css/bootstrap.min.css">
        <script src="../client/assets/bootstrap/js/popper.js"></script>
        <script src="../client/assets/bootstrap/js/bootstrap.min.js"></script>
        <link rel="stylesheet" href="../client/assets/css/mystyle.css">
        <link rel="stylesheet" href="../client/assets/css/cats.css">
        <link rel="stylesheet" href="../client/assets/css/colors.css">
        <link rel="stylesheet" href="../client/assets/css/factory.css">
        <link rel="stylesheet" href="../client/assets/css/frontend.css">
        <link rel="stylesheet" href="../client/assets/css/animation.css">
        <script type="text/javascript" src="../web3.min.js"></script>
    </head>
    <body>
        <div class=" light-b-shadow" align = "center">
            <p class="bg-white pt-0">Academy-kitties
            <button class ='red-btn'>Home</button>
            <button class ='red-btn'>Catalogue</button>
            <button class ='red-btn' onclick="location.href='../'">Kitties Factory</button>
            </p>
        </div>
        <div class="container p-5"  >
            <h1 class="c-white">Cat Catalogue</h1>
            <p class="c-white">Checkout the Kitties</p>
            <button class="white-btn" id="renderKitties">Render </button>
            <button class="white-btn" onclick="breedingKitties()">Breeding </button>
        </div>
        <p style="width:100%" id= "1">
        </p>
    </body>
        <script src="../client/assets/js/colors.js"></script>
        <script src="../client/assets/js/catCatalogue.js"></script>
        <script src="../client/assets/js/catFactory.js"></script>
        <script src="../abi.js"></script>  
</html>

catCatalogue

var colors = Object.values(allColors())
var web3 = new Web3(Web3.givenProvider);
var contractInstance;
var tokenCount; 
var arrayDNA = [];
var j= 0; 
var catBoxFull = '';
var breedIds =0; 
var catsIds = []; 

$(document).ready(function() {
  window.ethereum.enable().then(function(accounts){
    contractInstance = new web3.eth.Contract(window.abi, "0xc7E8420a2715fB2474963279AD91e57fcE2998e3", {from: accounts[0]});
    catCatalogue()
    })
});

function catCatalogue() {
    contractInstance.methods.totalSupply().call().then((res)=>{
      tokenCount = parseInt(res);
      for(var i=0; i<tokenCount; i++){
        kittiesDNA(i);
      } 
    })    
}


function kittiesDNA(i) { //i is ID from blokchain 
        contractInstance.methods.getKitty(i).call().then(function(res){
          var DNA = {
            headcolor: res[0].slice(0,2),
            "mouthcolor": res[0].slice(2,4),
            "eyescolor": res[0].slice(4,6),
            "earscolor": res[0].slice(6,8),
            "eyesShape": parseInt(res[0].slice(8,9)),
            "decorationPattern": parseInt(res[0].slice(9,10)),
            "decorationMidcolor": res[0].slice(10,12),
            "decorationSidescolor": res[0].slice(12,14),
            "animation":  parseInt(res[0].slice(14,15)),
            "lastNum":  res[0].slice(15,16),
            "motherId": res[2],
            "fatherId": res[3],
            "catGeneration": res[4],
            "birthDate": res[1],
            "id": i
            };
            arrayDNA.push(DNA);  
            createCatBox(i)
        })  
}

function createCatBox(id){
j++
    if (j<= tokenCount){
    var catBox = 
    `<div class="col-lg-4 catBoxCatalog m-2 light-b-shadow" id= "catBox`+id+`">
        <div class='cat' id= "cat`+id+`">
            <div class= 'ears' id= "ears`+id+`">
                <div class= 'rightear' id="rightear`+id+`">
                    <div class = 'innerear' id="innerear`+id+`"></div>
                </div>
                <div class= 'leftear' id="leftear`+id+`">
                    <div class= 'innerear id=`+id+`'></div>
                </div>
            </div>
            <div class= 'head' id= "head`+id+`">
                <div class= 'front' id= "front`+id+`"></div>
                <div class= 'nouse' id="nouse`+id+`"></div>
                <div class= 'eyes' id= "eyes`+id+`">
                    <div class = 'eye' id="eye`+id+`">
                        <div class = 'pupil'  id="pupil`+id+`"></div>
                        <div class= 'intoeye' id= "intoeye`+id+`"></div>
                    </div>
                    <div class = 'eye2' id="eye2`+id+`">
                        <div class = 'pupil' id= "pupil`+id+`"></div>
                        <div class= 'intoeye' id= "intoeye`+id+`"></div>
                    </div>
                </div>
                <div class= 'mouth' id="mouth`+id+`">
                    <div class= 'tongue' id= "tongue`+id+`"></div>
                </div>  
                <div class ='whiskergroup1' id= "whiskergroup1`+id+`">
                    <div class= 'whisker' id= "whisker`+id+`"></div>
                    <div class= 'whisker2' id= "whisker2`+id+`"></div>
                    <div class= 'whisker3' id= "whisker3`+id+`"></div>
                </div>
                <div class ='whiskergroup2' id="whiskergroup2`+id+`">
                    <div class= 'whisker4' id="whisker4`+id+`"></div>
                    <div class= 'whisker5' id= "whisker5`+id+`"></div>
                    <div class= 'whisker6' id= "whisker6`+id+`"></div>
                </div>
            </div>
            <div class = 'tail' id="tail`+id+`">
                <div class= 'intotail' id="intotail`+id+`"></div>
            </div>
            <div class = 'neck' id="neck`+id+`"></div>
            <div class= 'body' id="body`+id+`">                           
                <div class = 'belly' id="belly`+id+`"> </div>
                <div class = 'legs' id="legs`+id+`">
                    <div class = 'rightleg' id="rightleg`+id+`"></div>
                    <div class = 'leftleg' id="leftleg`+id+`"></div>
                </div>
            </div>      
        </div>
        <br>
        <br>
        <div class="dnaDiv" id="catDNA">
            DNA:
            <!-- Colors -->
            <span id="dnabody`+id+`"></span>
            <span id="dnamouth`+id+`"></span>
            <span id="dnaeyes`+id+`"></span>
            <span id="dnaears`+id+`"></span>
            <!-- Cattributes -->
            <span id="dnashape`+id+`"></span>
            <span id="dnadecoration`+id+`"></span>
            <span id="dnadecorationMid`+id+`"></span>
            <span id="dnadecorationSides`+id+`"></span>
            <span id="dnaanimation`+id+`"></span>
            <span id="dnaspecial`+id+`"></span>
        </div>   
        <div class="dnaDiv" id="catStatistics">
        <br>    
            Mom ID: <span id= "momId`+id+`"></span>
            Dad ID: <span id= "dadId`+id+`"></span>
            Gen: <span id= "generation`+id+`"></span><br>
            <!--Birth Time: <span id= "birthTime"></span>-->
            <label for="breedCheck" > Breeding</label>
            <input type="checkbox" id="breedCheck`+id+`" onclick="breeding(`+id+`)">
            <p id="breedText`+id+`" style="display:none">CHECKED! `+id+`</p>
        </div>
    </div>`;
    //document.getElementById("1").append(catBox);
    //document.body.innerHTML = `<h1>${catBoxFull} </h1>`
    }
catBoxFull = catBoxFull.concat(catBox);
document.getElementById('1').innerHTML = catBoxFull;
}


    $('#renderKitties').click(()=>{
    for(var l=0; l<tokenCount; l++){ 
        headColor(colors[arrayDNA[l].headcolor],arrayDNA[l].headcolor, l)
        tailColor(colors[arrayDNA[l].mouthcolor],arrayDNA[l].mouthcolor,l)
        eyeColor(colors[arrayDNA[l].eyescolor],arrayDNA[l].eyescolor, l)
        earColor(colors[arrayDNA[l].earscolor],arrayDNA[l].earscolor, l)
        eyeVariation(arrayDNA[l].eyesShape,l)  
        decorationVariation(arrayDNA[l].decorationPattern, l)
        pattern(colors[arrayDNA[l].decorationMidcolor],arrayDNA[l].decorationMidcolor, l)
        pattern2(colors[arrayDNA[l].decorationSidescolor],arrayDNA[l].decorationSidescolor, l)
        animationVariation(arrayDNA[l].animation, l) 
        $(`#momId${l}`).html(arrayDNA[l].motherId)
        $(`#dadId${l}`).html(arrayDNA[l].fatherId)
        $(`#birthTime${l}`).html(arrayDNA[l].birthDate)
        $(`#generation${l}`).html(arrayDNA[l].catGeneration) 
        $(`#dnaspecial${l}`).html(arrayDNA[l].lastNum)
     }
    })

function breeding(id) {
    var checkBox = document.getElementById(`breedCheck${id}`);
    var text = document.getElementById(`breedText${id}`);
    if (checkBox.checked == true){
        text.style.display = "block";
        breedIds++;
        catsIds.push(id);
    } else {
        text.style.display = "none";
        breedIds--;
  }
}

function breedingKitties () {
    if (breedIds=== 2){ 
        contractInstance.methods.breed(catsIds[0], catsIds[1]).send(function(error, txHash) {
            if(error){
                console.log(error)
                breedIds =0;
                array.splice(0, array.length)
            }
            else {
                console.log(txHash)   
                breedIds =0;
                array.splice(0, array.length) 
            }    
        }); 
        contractInstance.once('Birth', function(error, event){ //listener
            if(event) {
                console.log(event)
              alert(`Owner: ${event.returnValues.owner} \nBlockHash: ${event.blockHash} 
              \nblocknumber: ${event.blockNumber} \nContract: ${event.address}
              \nGenes: ${event.returnValues.genes} \nDadID ${event.returnValues.dadId}
              \nMumID ${event.returnValues.mumId} \nKittenID ${event.returnValues.kittenId}`)
            }
            else
                console.log(error)
      });
    } 
    else {
        alert("incorrect")
    }
}

as you can see i used a click handler with a button i cannot make render the page automatically (i received errors and errors for this )
with this works ok

html 
 <button class="white-btn" id="renderKitties">Render </button>

js
$('#renderKitties').click(()=>{
    for(var l=0; l<tokenCount; l++){ 
        headColor(colors[arrayDNA[l].headcolor],arrayDNA[l].headcolor, l)
        tailColor(colors[arrayDNA[l].mouthcolor],arrayDNA[l].mouthcolor,l)
        eyeColor(colors[arrayDNA[l].eyescolor],arrayDNA[l].eyescolor, l)
        earColor(colors[arrayDNA[l].earscolor],arrayDNA[l].earscolor, l)
        eyeVariation(arrayDNA[l].eyesShape,l)  
        decorationVariation(arrayDNA[l].decorationPattern, l)
        pattern(colors[arrayDNA[l].decorationMidcolor],arrayDNA[l].decorationMidcolor, l)
        pattern2(colors[arrayDNA[l].decorationSidescolor],arrayDNA[l].decorationSidescolor, l)
        animationVariation(arrayDNA[l].animation, l) 
        $(`#momId${l}`).html(arrayDNA[l].motherId)
        $(`#dadId${l}`).html(arrayDNA[l].fatherId)
        $(`#birthTime${l}`).html(arrayDNA[l].birthDate)
        $(`#generation${l}`).html(arrayDNA[l].catGeneration) 
        $(`#dnaspecial${l}`).html(arrayDNA[l].lastNum)
     }
    })

my problem is when I call a function to render everything
there are errors calling the data that i need from the array but i don understand this, maybe i am so bad for async programming

function catCatalogue() {
    contractInstance.methods.totalSupply().call().then((res)=>{
      tokenCount = parseInt(res);
      for(var i=0; i<tokenCount; i++){
        kittiesDNA(i);
      } 
      **renderALL();** // i tried so much here 
    })    
}

function renderALL() {
    //$('#renderKitties').click(()=>{
    for(var l=0; l<tokenCount; l++){ 
        headColor(colors[arrayDNA[l].headcolor],arrayDNA[l].headcolor, l)
        tailColor(colors[arrayDNA[l].mouthcolor],arrayDNA[l].mouthcolor,l)
        eyeColor(colors[arrayDNA[l].eyescolor],arrayDNA[l].eyescolor, l)
        earColor(colors[arrayDNA[l].earscolor],arrayDNA[l].earscolor, l)
        eyeVariation(arrayDNA[l].eyesShape,l)  
        decorationVariation(arrayDNA[l].decorationPattern, l)
        pattern(colors[arrayDNA[l].decorationMidcolor],arrayDNA[l].decorationMidcolor, l)
        pattern2(colors[arrayDNA[l].decorationSidescolor],arrayDNA[l].decorationSidescolor, l)
        animationVariation(arrayDNA[l].animation, l) 
        $(`#momId${l}`).html(arrayDNA[l].motherId)
        $(`#dadId${l}`).html(arrayDNA[l].fatherId)
        $(`#birthTime${l}`).html(arrayDNA[l].birthDate)
        $(`#generation${l}`).html(arrayDNA[l].catGeneration) 
        $(`#dnaspecial${l}`).html(arrayDNA[l].lastNum)
     }
    //})
}

image

this is the only problem the rest is working (with the button all works fine)

3 Likes

hi @kenn.eth, solved it! Iā€™d forgotten to update my abi.js file, so breed wasnā€™t showing up as one of the methods available. Updated the abi.js file, refreshed the website, and now itā€™s working!

1 Like

Hi @kenn.eth

Sorry for my late reply, because i moved ahead to finish the Ethereum Smart Contract Security Course and it was great learning and now I am revisiting this subject.

You have two clear errors.
2021-06-05_19h35_22

Well Below I am sharing with you my catSettings.js, catFactory.js, catConstants.js and colors.js code. I honestly have tried again but I couldnā€™t find any error ( or TypeError)

catSettings.js :point_down:

function getDna(){
  try {
    let dna = ''
    dna += $('#dnabody').html()
    dna += $('#dnamouth').html()
    dna += $('#dnaeyes').html()
    dna += $('#dnaears').html()
    dna += $('#dnashape').html()
    dna += $('#dnadecoration').html()
    dna += $('#dnadecorationMid').html()
    dna += $('#dnadecorationSides').html()
    dna += $('#dnaanimation').html()
    dna += $('#dnaspecial').html()

    if (dna.length !== 16 ) throw `DNA string ('${dna}') length should be 16 (not ${dna.length} digits)`

    return BigInt(dna)
  }
  catch (error) {
    console.log(`Error In getDna(): ${error}`)
  }
}


function renderCat(cat, idCat=""){
  try {
    headColor(cat.dna.headColor, idCat)
    mouthColor(cat.dna.mouthColor, idCat)
    eyesColor(cat.dna.eyesColor, idCat)
    earsColor(cat.dna.earsColor, idCat)
    eyeVariation(cat.dna.eyesShape, idCat)
    decorationVariation(cat.dna.decorationPattern, idCat)
    midDecorationColor(cat.dna.decorationMidColor, idCat)
    sidesDecorationColor(cat.dna.decorationSidesColor, idCat)
    animationStyle(cat.dna.animation, idCat)

    // Display Special DNA digit
    $(`${idCat} #dnaspecial`).html(cat.dna.lastNum) // Update DNA display (below cat)

    // Display Cats' Generation
    $(`${idCat}`).find('#catGenNum').html(cat.gen)

    // Display Cats' Price (if it has one)
    if (cat.price) $(`${idCat}`).find('#catPrice').html("PRICE: " + cat.price + " ETH")

    // Display Cats' status
//    $(`${idCat}`).find('#catStatus').html("TEST")

  }
  catch (error){
    console.log(`Error In renderCat, idCat=""): ${error}`)
  }
}


function updateSliders(dna){
  try {
    $('#bodycolor').val(dna.headColor)             //Update slider's value
    $('#headcode').html('code: '+dna.headColor)    //Update slider's badge

    $('#mouthcolor').val(dna.mouthColor)
    $('#mouthcode').html('code: '+dna.mouthColor)

    $('#eyescolor').val(dna.eyesColor)
    $('#eyescode').html('code: '+dna.eyesColor)

    $('#earscolor').val(dna.earsColor)
    $('#earscode').html('code: '+dna.earsColor)

    $('#eyesshape').val(dna.eyesShape)
    $('#eyename').html(eyeVariations[dna.eyesShape].name)

    $('#decorationpattern').val(dna.decorationPattern)
    $('#decorationname').html(decorationVariations[dna.decorationPattern].name)

    $('#decorationmidcolor').val(dna.decorationMidColor)
    $('#midbirthmarkcode').html('code: '+dna.decorationMidColor)

    $('#decorationsidescolor').val(dna.decorationSidesColor)
    $('#sidebirthmarkscode').html('code: '+dna.decorationSidesColor)

    $('#animationstyle').val(dna.animation)
    $('#animationcode').html(animationVariations[dna.animation].name)
  }
  catch (error){
    console.log(`Error In updateSliders(dna): ${error}`)
  }
}


//EVENT LISTENERS

// Changing cat's Body' colors
$('#bodycolor').change(()=>{
    var colorVal = $('#bodycolor').val()
    $('#headcode').html('code: '+ colorVal) //This updates text of the badge next to the slider
    headColor(colorVal)


})

// Changing Cat's Mouth color
$('#mouth_tail_color').change(()=>{
  var colorVal = $('#mouth_tail_color').val()
  $('#mouthcode').html('code: ' + colorVal) // This updates text of the badge next to the slider
  mouthColor(colorVal)


})

//Changing cat's eyes color
$('#eyescolor').change(()=>{
  var colorVal = $('#eyescolor').val()
  $('#eyescode').html('code: ' + colorVal) // This updates text of the badge next to the slider
  eyesColor(colorVal)

})

//Changing cat's ears colors
$('#earscolor').change(()=>{
  var colorVal = $('#earscolor').val()
  $('#earscode').html('code: ' + colorVal) // This updates text of the badge next to the slider
  earsColor(colorVal)

})

//Changing Cat eyes Shape
$('#eyesshape').change(()=>{
  var shape = parseInt($('#eyesshape').val())
  $('#eyename').html(eyeVariations[shape].name)
  eyeVariation(shape)

})

//Changing Decoration pattern
$('#decorationpattern').change(()=>{
  var pattern = parseInt($('#decorationpattern').val())
  $('#decorationname').html(decorationVariations[pattern].name)
  decorationVariation(pattern)
})

//Changing The Side & Mid Birthmarks colors
$('#decorationsidescolor').change(()=>{
  var colorVal = $('#decorationsidescolor').val()
  $('#sidebirthmarkscode').html('code: '+ colorVal) //This updates text of the badge next to the slider
  sidesDecorationColor(colorVal)
})
$('#decorationmidcolor').change(()=>{
  var colorVal = $('#decorationmidcolor').val()
  $('#midbirthmarkcode').html('code: '+ colorVal) //This updates text of the badge next to the slider
  midDecorationColor(colorVal)
})

//Changing the Animation Style :
$('#animationstyle').change(()=>{
  var animationVal = parseInt($('#animationstyle').val())
  $('#animationcode').html(animationVariations[animationVal].name)
  animationStyle(animationVal)
})

catFactory.js :point_down:



//This function changes the color of Head and Chest
function headColor(code,idCat = "") {
    $(`${idCat}.cat__head, ${idCat}.cat__chest`).css('background', '#' + colors[code])  //This changes the color of the cat
    $(`${idCat}#dnabody`).html(code) //This updates the body color part of the DNA that is displayed below the cat


}

// This function changes the color of Mouth and tail
function mouthColor(code,idCat = ""){
  $(`${idCat}.cat__mouth-left, ${idCat}.cat__mouth-right, ${idCat}.cat__tail`).css('background', '#' + colors[code]) //This changes the Cat's Mouth and Tail Colors
  $(`${idCat}#dnamouth`).html(code) // This updates the Mouth and Tail color part of the DNA that is displayed below the cat

}

//This function changes the color of Cat's eyes
function eyesColor(code, idCat = ""){
  $(`${idCat}.cat__eye span.pupil-left, ${idCat}.cat__eye span.pupil-right`).css('background', '#' + colors[code]) //This changes the Cat's Mouth and Tail Colors
  $(`${idCat}#dnaeyes`).html(code) // This updates the Mouth and Tail color part of the DNA that is displayed below the cat


}

//This function changes the color of Cat's ears and Paws
function earsColor(code, idCat = ""){
  $(`${idCat}.cat__ear--left, ${idCat}.cat__ear--right, ${idCat}.cat__paw-left, ${idCat}.cat__paw-right`).css('background', '#' + colors[code]) //This changes the Cat's ears Colors
  $(`${idCat}#dnaears`).html(code) //This updates the Ears color part of the DNA that is displayed below the Cat


}

//###################################################
//USING BELOW FUNCTIONS TO CHANGE CATTRIBUTES
//###################################################

//Changing Eye shapes
function eyeVariation(num, idCat = "") {
    normalEyes(idCat) //Reset eyes
    $(`${idCat}#dnashape`).html(num)//This updates the Eyes shape part of the DNA that is displayed below the Cat
    eyeVariations[num].setEyesFunc(idCat)
}
//########################################################################################
  //  switch (num) {
  //      case 1:
  //          normalEyes()
  //          $('#eyename').html('Basic Eyes')// Set the badge of the eye to 'Basic'
  //          break
  //      case 2:
  //          normalEyes()//reset
  //          $('#eyename').html('Chill Eyes')//Set the badge to "Chill"
  //          eyesType1()//Change the eye shape by bringing a Solid border-top 15 px
  //          break
  //      case 3:
  //          normalEyes()//reset
  //          $('#eyename').html('Smile Eyes')//Set the badge to "Smile"
  //          eyesType2()//Change the eye shape by bringing a Solid border- bottom15 px
  //          break
  //      case 4:
  //          normalEyes()//reset
  //          $('#eyename').html('Cool Eyes')//Set the badge to "Cool"
  //          eyesType3()//Change the eye shape by bringing a Solid border-right 15 px
  //          break
  //      case 5:
  //          normalEyes()//reset
  //          $('#eyename').html('Dotted Eyes')//Set the badge to "Dotted Eyes"
  //          eyesType4()//Change the eye shape by bringing a border-style: dotted
  //          break
  //  }




function normalEyes(idCat) {
    //Reset eye Lids to fully open
    $(`${idCat}.cat__eye`).find('span').css('border', 'none')
    // Reset pupil to round and centered
    $(`${idCat} .cat__eye`).find('span').css('width', '42px')
    $(`${idCat} .pupil-left`).css('left', '42px')
    $(`${idCat} .pupil-right`).css('left', '166px')
}

function eyesType1(idCat) {
    $(`${idCat}.cat__eye`).find('span').css('border-top', '15px solid')
}

function eyesType2(idCat) {
    $(`${idCat}.cat__eye`).find('span').css('border-bottom', '15px solid')
}

function eyesType3(idCat) {
    $(`${idCat}.cat__eye`).find('span').css('border-right', '15px solid')
}

function eyesType4(idCat) {
    $(`${idCat}.cat__eye`).find('span').css('border-style', 'Dotted')
}

//###################################################################################

//Changing Cat BirthMark Dimensions + Rotation
function decorationVariation(num, idCat="") {
  normalDecoration(idCat)
  $(`${idCat} #dnadecoration`).html(num)   // Update DNA display (below cat)
  decorationVariations[num].setDecorationFunc(idCat)
}

//#########################################################################################
  //  switch (num) {
  //    case 1:
  //          normalDecoration()
  //          $('#decorationname').html('Basic Forehead Patches')// Set the Badge to Decoration pattern Basic
  //          break
  //      case 2:
  //          normalDecoration()
  //          $('#decorationname').html('Angled Forehead Patches')// Set the Badge to Decoration pattern - Angled patches
  //          normalDecoration1()
  //          break
  //      case 3:
  //          normalDecoration()
  //          $('#decorationname').html('Smaller Forehead Width Patches')// Set the Badge to Decoration pattern - Smaller Patches
  //          normalDecoration2()
  //          break
  //      case 4:
  //          normalDecoration()
  //          $('#decorationname').html('Smaller Forehead Height Patches')// Set the Badge to Decoration pattern - Smaller Patches
  //          normalDecoration3()
  //          break
  //  }




function normalDecoration(idCat) {
    //Remove all style from other decorations
    //In this way we can also use normalDecoration() to reset the decoration style
    $(`${idCat}.cat__head-dots`).css({ "transform": "rotate(0deg)", "height": "48px", "width": "14px", "top": "1px", "border-radius": "0 0 50% 50%" })
    $(`${idCat}.cat__head-dots_first`).css({ "transform": "rotate(0deg)", "height": "35px", "width": "14px", "top": "1px", "border-radius": "50% 0 50% 50%" })
    $(`${idCat}.cat__head-dots_second`).css({ "transform": "rotate(0deg)", "height": "35px", "width": "14px", "top": "1px", "border-radius": "0 50% 50% 50%" })
}


function normalDecoration1(idCat) {
    //Remove all style from other decorations
    //In this way we can also use normalDecoration() to reset the decoration style
    $(`${idCat}.cat__head-dots`).css({ "transform": "rotate(0deg)", "height": "48px", "width": "14px", "top": "1px", "border-radius": "0 0 50% 50%" })
    $(`${idCat}.cat__head-dots_first`).css({ "transform": "rotate(45deg)", "height": "35px", "width": "14px", "top": "1px", "border-radius": "50% 0 50% 50%" })
    $(`${idCat}.cat__head-dots_second`).css({ "transform": "rotate(-45deg)", "height": "35px", "width": "14px", "top": "1px", "border-radius": "0 50% 50% 50%" })
}

function normalDecoration2(idCat) {
    //Remove all style from other decorations
    //In this way we can also use normalDecoration() to reset the decoration style
    $(`${idCat}.cat__head-dots`).css({ "transform": "rotate(0deg)", "height": "48px", "width": "8px", "top": "1px", "border-radius": "0 0 50% 50%" })
    $(`${idCat}.cat__head-dots_first`).css({ "transform": "rotate(0deg)", "height": "35px", "width": "8px", "top": "1px", "border-radius": "50% 0 50% 50%" })
    $(`${idCat}.cat__head-dots_second`).css({ "transform": "rotate(0deg)", "height": "35px", "width": "8px", "top": "1px", "border-radius": "0 50% 50% 50%" })
}

function normalDecoration3(idCat) {
    //Remove all style from other decorations
    //In this way we can also use normalDecoration() to reset the decoration style
    $(`${idCat}.cat__head-dots`).css({ "transform": "rotate(0deg)", "height": "24px", "width": "8px", "top": "1px", "border-radius": "0 0 50% 50%" })
    $(`${idCat}.cat__head-dots_first`).css({ "transform": "rotate(0deg)", "height": "20px", "width": "8px", "top": "1px", "border-radius": "50% 0 50% 50%" })
    $(`${idCat}.cat__head-dots_second`).css({ "transform": "rotate(0deg)", "height": "20px", "width": "8px", "top": "1px", "border-radius": "0 50% 50% 50%" })
}

//########################################################################################################

//This changes the Side BirthMark Colors
function sidesDecorationColor(code, idCat= "") {
    $(`${idCat}.cat__head-dots_first , ${idCat}.cat__head-dots_second`).css('background', '#' + colors[code])  //This changes the color of the cat's Side BirthMark
    $(`${idCat}#dnadecorationSides`).html(code) //This updates the Side Birthmarks color part of the DNA that is displayed below the cat
}

//This changes the Mid BirthMark colors
function midDecorationColor(code, idCat ="") {
    $(`${idCat}.cat__head-dots`).css('background', '#' + colors[code])  //This changes the color of the cat's Mid Birthmark
    $(`${idCat}#dnadecorationMid`).html(code) //This updates the Mid Birthmark color part of the DNA that is displayed below the cat
  }


//#################################################################################################################
//This Function changes the animation style
function animationStyle(num,idCat = ""){
  resetAnimation(idCat) //Reset animations
  $(`${idCat} #dnaanimation`).html(num)   // Update DNA display (below cat)
  animationVariations[num].setAnimationFunc(idCat)
}

//#################################################################################################################
//  switch (num) {
//    case 1 :
//    movingHeadAnimation()
//    $('#animationcode').html('Moving Head')//It sets the Badge to Moving Head style
//    break
//    case 2 :
//    bigHeadAnimation()
//    $('#animationcode').html('Big Head') // It sets the Badge to Scaled Head style
//    break
//    case 3 :
//    translatedHeadAnimation()
//    $('#animationcode').html("Translated Head")//It setsthe  Badge to Transitioned/Transported Head style
//    break
//    case 4 :
//    movingTailAnimation()
//    $('#animationcode').html('Moving Tail')// It sets the badge to Moving Tail animation style
//    break
//  }




function animationType1(idCat) {  //Head rotates and moves
  $(`${idCat}#head`).addClass('movingHead')
}

function animationType2(idCat) {  //Head gets scaled
  $(`${idCat}#head`).addClass('scalingHead')

}


function animationType3(idCat) { //Head gets translated
  $(`${idCat}#head`).addClass('translatingHead')
}


function animationType4(idCat) { //Tail starts Moving
  $(`${idCat}#tail`).addClass('movingTail')
}

function resetAnimation(idCat){
  $(`${idCat}#head`).removeClass('movingHead')
  $(`${idCat}#head`).removeClass('scalingHead')
  $(`${idCat}#head`).removeClass('translatingHead')
  $(`${idCat}#tail`).removeClass('movingTail')


}

catConstants.js :point_down:

var colors = Object.values(allColors())

const defaultDNA = {
    "headColor" : 10,
    "mouthColor" : 13,
    "eyesColor" : 96,
    "earsColor" : 10,
    //Cattributes
    "eyesShape" : 1,
    "decorationPattern" : 1,
    "decorationMidColor" : 13,
    "decorationSidesColor" : 13,
    "animation" : 0,
    "lastNum" : 1
    }

const defaultCat = {
    id: "",
    dna: defaultDNA,
    gen: ""
}

const eyeVariations = [
    {
      "name" : "Basic Eyes",
      "setEyesFunc" : normalEyes
    },
    {
      "name" : "Smiling Eyes",
      "setEyesFunc" : eyesType1
    },
    {
        "name" : "Shy Girl eyes",
        "setEyesFunc" : eyesType2
    },
    {
        "name" : "Chill",
        "setEyesFunc" : eyesType3
    },
    {
        "name" : "Dotted Eyes",
        "setEyesFunc" : eyesType4
    }
  ]

const decorationVariations = [
    {
        "name" : "Standard Stripes",
        "setDecorationFunc" : normalDecoration
    },
    {
        "name" : "Angular Stripes",
        "setDecorationFunc" : normalDecoration1
    },
    {
        "name" : "Big Stripes",
        "setDecorationFunc" : normalDecoration2
    },
    {
        "name" : "Small Stripes",
        "setDecorationFunc" : normalDecoration3
    }
]

const animationVariations = [
    {
        "name" : "Moving Head",
        "setAnimationFunc" : animationType1
    },
    {
        "name" : "Scaling Head",
        "setAnimationFunc" : animationType2
    },
    {
        "name" : "Translating Head",
        "setAnimationFunc" : animationType3
    },
    {
        "name" : "Moving Tail",
        "setAnimationFunc" : animationType4
    }
]

colors.js :point_down:


function allColors(){
  return colorPallete;
}


var colorPallete = {00: "ae494f",
01: "9a3031",
02: "8cd42e",
03: "a0417a",
04: "91c656",
05: "299f7a",
06: "c65d1e",
07: "b2bbd6",
08: "2d4024",
9: "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: "353f9",
28: "5d4993",
29: "ba8d15",
30: "da2457",
31: "ff17fe",
32: "d6e81d",
33: "daf2db",
34: "19b510",
35: "18e26f",
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: "bae4f",
51: "b76d01",
52: "8e8207",
53: "285b9f",
54: "c4422a",
55: "f1eaa7",
56: "e3a0cc",
57: "65c116",
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: "cff1dd",
72: "8805fb",
73: "fe99d2",
74: "c52f14",
75: "e31c54",
76: "d010eb",
77: "b83436",
78: "c294b6",
79: "564a6c",
80: "531bcf",
81: "c04b8c",
82: "3cd2ef",
83: "82286c",
84: "aa2639",
85: "86be6c",
86: "e62102",
87: "5471fc",
88: "5c089",
89: "703c75",
90: "9a8e8f",
91: "8b9307",
92: "fcbc82",
93: "ea5978",
94: "b8e370",
95: "43474b",
96: "262d2b",
97: "ddd67e",
98: "344867"}




//Random color
function getColor() {
    const randomColor = Math.floor(Math.random() * 16777215).toString(16);
    return randomColor
}

//Generate colors for pallete
function genColors(){
    const colors = []
    for(const i = 10; i < 99; i ++){
      const color = getColor()
      colors[i] = color
    }
    return colors
}

I am honestly unable to find any errors after consistent trying, so please help me :pray: :pray:

Also, Below is my helperFunctions.js file :point_down:

tfunction getRandomIntegerBetween(low, high){
    try {
      if (low<0) throw "Error: Only supports positive integers - low is negative!"
      if (low>high) throw "Error: low is greater than high!"

      const rangeInclusive = high - low + 1
      const RandomValue = Math.floor(Math.random() * rangeInclusive) + low

      return RandomValue
    }
    catch(error) {
      throw(`In getRandomIntegerBetween(${low}, ${high}): ${error}`)
    }
  }


  function getParamFromUrl(url, paramId) {
    try {
      const startParamIdPos = url.lastIndexOf(paramId)
      if (startParamIdPos == -1) {
          throw new Error(`Parameter: "${paramId}" not present in url: "${url}"`)
      }
      const startParamValPos = startParamIdPos + paramId.length

      const endDelimPos = url.indexOf("&", startParamValPos)
      const endParamValPos = (endDelimPos > -1)? endDelimPos: url.length

      const param = url.substring( startParamValPos, endParamValPos )

      return param
    }
    catch(error) {
      throw("HelperFunctions.js: In getParamFromUrl(url, paramId): " + error)
    }
  }

I have just copy / pasted the code, but I havenā€™t understood it yet and it seems also not to be working
So please Help me in figuring it out :pray: :pray:

In Fact I would suggest if you can spare some time and run my entire code and see where and why these errors are coming ?
I really want to understand and finish these abnormalities, before i move forward on to other courses.

Thanks again :pray: :pray:

This is my GitHub code:

Please download this zip folder : it contains all my code:
https://github.com/Suveett/CryptoKitties/blob/main/CryptoKitties.zip

Please donā€™t use the other code, itā€™s not been updated yet.

Thanks a ton in advance

Suveett kalra
(Su.kal Crypto)

Hey guys, hope youā€™re all well.
When i try and create a new kitty, it throws a few errors and they donā€™t make sense.
The first error message is:
Screenshot 2021-06-15 at 12.40.45
Iā€™m interpreting the above message as saying i have not declared the contract address in the index.js file. Even though i have copied and pasted the deployed contract address (and i triple checked).

.
The second error message is:
Screenshot 2021-06-15 at 12.43.45
Which i have never seen before and donā€™t quite understand even after research.

.
And then finally this other error message comes up when i navigate to my CATalogue page:
Screenshot 2021-06-15 at 12.50.12

My abs.js file is up-to-date and my solidity contracts have been deployed + migrated + copied and pasted the contract address to all my js files before opening the python web server.

My up-to-date Github repo is here: https://github.com/olfrank/Crypto_Cats

Thanks.

Hey @ol_frank I think your problem is coming from marketplace contract. You are calling the marketplace address in the marketplaceInstance but you got it mute. So this is causing the error.
2021-06-15_15h36_59

hey @Su.kal.Crypto the code zip file you send is just empty.
I find some issues
This is a typo. you wrote tfunction
2021-06-15_15h39_25

Also notice that the error you are getting comes from not using a correct index number for calling the property you wish. So, for this constant decorationVariations youy should log the index you are using to make sure is right,

Hi @kenn.eth

Thanks, I was just about to write to you that i figured this mistake already and sorted out the index values.

But Thanks a ton indeed for your effort and super quick Help.
And Now, I am stuck again. I am literally having nightmares in completing this Dapp (because of my not so good knowledge of JavaScript. Although I am really trying hard to understand the logic of each Function line by line by line, but just when I think I have grasped almost everything a New error crops up. I tried googling for solutions but couldnā€™t get to the crux of it )

I am now having the below error in createKittie() func

Screenshot 2021-06-15 at 9.03.09 PM

Error In createKittie: Error: invalid number value (arg="_genes", coderType="uint256", value="9690311201456811")

Seems to be a conversion issue between uint256 & BigInt in the getDna()

Also another question : in catsettings.js getDna() has been specifically called to return a BigInt whereas the Kittycontract.sol function createKittyGen0(uint256 _genes) public onlyOwner returns(uint256){
require(gen0Counter < CREATION_LIMIT_GEN0);
gen0Counter ++;

return _createKitty(0,0, _genes, 0, msg.sender);

}
returns a uint256

Also, One more question: actually can this statement return _createKitty(0,0, _genes, 0, msg.sender); be called a uint256 ?
Does Solidity compiler return a uint256 equivalent of this statement???

How does all this Interact with each other (if at all it does) , because the error seems in createKittie() in catSettings.js and not in the solidity Kittycontract and its function createKittyGen0, then why this error ?? :thinking: :thinking:

Error In createKittie: Error: invalid number value (arg="_genes", coderType="uint256", value="9690311201456811")

I donā€™t know If I am making sense, i am so god damned confused, tired and almost giving up, because there is no uint256 declaration in the getDna() function of catSettings.js


function createKittie(){
  try {
    const dnaStr = getDna()
    KITTY_CONTRACT_INSTANCE.methods.createKittyGen0(dnaStr).send({}, function(err, txHash){
        if (err) console.log(err)
        else console.log(txHash)
    })
  }
  catch(error){
    console.log(`Error In createKittie: ${error}`)
  }
}

function getDna(){
  try {
    let dna = ''
    dna += $('#dnabody').html()
    dna += $('#dnamouth').html()
    dna += $('#dnaeyes').html()
    dna += $('#dnaears').html()
    dna += $('#dnashape').html()
    dna += $('#dnadecoration').html()
    dna += $('#dnadecorationMid').html()
    dna += $('#dnadecorationSides').html()
    dna += $('#dnaanimation').html()
    dna += $('#dnaspecial').html()

    if (dna.length !== 16 ) throw `DNA string ('${dna}') length should be 16 (not ${dna.length} digits)`

    return BigInt(dna)
  }
  catch (error) {
    console.log(`Error In getDna(): ${error}`)
  }
}

Thanks and awaiting revert

Suveett Kalra
(Su.Kal Crypto)

Ok cool ! try to pass this dna as a string to your createKittyGen0(). You can use the toString() JS function.
Something like :

const dnaStr = dnaStr = getDna().toString()
//Then call your function 
KITTY_CONTRACT_INSTANCE.methods.createKittyGen0(dnaStr)....

When you call from JS function using w3 you get just strings and numbers.

Hi @kenn.eth

I did exactly as you told me :point_down:


function createKittie(){
  try {
    const dnaStr = dnaStr = getDna().toString()
    KITTY_CONTRACT_INSTANCE.methods.createKittyGen0(dnaStr).send({}, function(err, txHash){
        if (err) console.log(err)
        else console.log(txHash)
    })
  }
  catch(error){
    console.log(`Error In createKittie: ${error}`)
  }
}

And now its showing error :point_down:

Error In createKittie: ReferenceError: Cannot access 'dnaStr' before initialization

What does this Mean ??

Also i understand your comment below here :point_down:

When you call from JS function using w3 you get just strings and numbers.

But how does solidity understand it when the Kittycontract is being called from my index.js using w3 passing a ā€œstringā€ input , whereas the function clearly defines uint256 as input ? :point_down:

function getKitty(uint256 _newKittenId) public view returns() {}

Please clarify this too !!

Thanks and Regards

Su.kal Crypto

1 Like

Hi @kenn.eth

I have resolved this issue just by changing the code to the following and Now i magically donā€™t see the error:


function createKittie(){
  try {
    const dnaStr = getDna().toString()
    KITTY_CONTRACT_INSTANCE.methods.createKittyGen0(dnaStr).send({}, function(err, txHash){
        if (err) console.log(err)
        else console.log(txHash)
    })
  }
  catch(error){
    console.log(`Error In createKittie: ${error}`)
  }
}

Now i see No errors but somehow the cats are not displaying on my Marketplace.html page and even on the Catalogue.html page.
I cannot understand why ? :thinking:

I have also uploaded the zip files on Github now and also updated the individual files on Github (I personally feel accessing the individual files will be easier, because somehow the zip folders arenā€™t displaying anything (when downloading) - although the same zip folders are showing all files on my Desktop)

Please Help :pray: :pray: I am literally on the verge of giving up (although I am giving it one last shot simply because of Your Motivations)

https://github.com/Suveett/CryptoKitties.git

Thanks and Best Regards

Su.Kal Crypto
(Suveett Kalra )

1 Like

Hi @Su.kal.Crypto please send me the errors about the market place or just show me the way you are rendering the cats.

Thats because we have this w3 library doing the magic behind. Its have the functions to communicate with metamask wich is the bridge to communicate with the blockchain.

Hi @kenn.eth
Sorry for my Late reply, but today i was endlessly trying to resolve the issue Myself.
I even Created Unit Tests so I can check what I am doing wrong :point_down:


const KittyMarketPlace = artifacts.require("KittyMarketPlace");
const Kittycontract = artifacts.require("Kittycontract");
const truffleAssert = require("truffle-assertions");

contract("Kittycontract", async (accounts)=> {
  let instance;

  beforeEach(async () => {
    instance = await Kittycontract.new();

  })


  it("Shouldn't Allow Non Owner to createKittyGen0", async() => {
    await truffleAssert.fails(instance.createKittyGen0(1234, {from: accounts[1]}), truffleAssert.ErrorType.REVERT)
  })
  it("Should Set All Kitty Mappings correctly", async()=> {
    await truffleAssert.passes(instance.createKittyGen0(1234, {from:accounts[0]}),truffleAssert.ErrorType.REVERT)
    let kitty = await instance.getKitty(1)
    assert(kitty._genes.toNumber() === 1234, kitty._mumId.toNumber() === 0, kitty._dadId.toNumber() === 0, kitty._generation.toNumber() === 0, "Mappings not Set Correctly" )
  })
  it("Should Set All Kitty Mappings correctly even for 16 digit genes", async()=> {
    await truffleAssert.passes(instance.createKittyGen0("1234567890123456", {from:accounts[0]}),truffleAssert.ErrorType.REVERT)
    let kitty = await instance.getKitty(1)
    assert(kitty._genes.toNumber() === 1234567890123456, kitty._mumId.toNumber() === 0, kitty._dadId.toNumber() === 0, kitty._generation.toNumber() === 0, "Mappings not Set Correctly" )
  })
  it("Should show Correct balance of Owner", async() => {
    await truffleAssert.passes(instance.createKittyGen0(1234, {from:accounts[0]}),truffleAssert.ErrorType.REVERT)
    await truffleAssert.passes(instance.createKittyGen0(12345, {from:accounts[0]}),truffleAssert.ErrorType.REVERT)
    let balance = await instance.balanceOf(accounts[0])
    assert(balance.toNumber() === 2, "Balance of owner not showing Correctly")
  })
  it("Should show Correct Total Supply of Kitties", async() => {
    await truffleAssert.passes(instance.createKittyGen0(1234, {from:accounts[0]}),truffleAssert.ErrorType.REVERT)
    await truffleAssert.passes(instance.createKittyGen0(12345, {from:accounts[0]}),truffleAssert.ErrorType.REVERT)
    let totalSupply = await instance.totalSupply()
    assert(totalSupply.toNumber() === 3, "Total Supply not showing Correctly")
  })
  it("Should display ownershipCertificate and tokenOwnershipCount Mappings correctly", async()=> {
    await truffleAssert.passes(instance.createKittyGen0(1234, {from:accounts[0]}),truffleAssert.ErrorType.REVERT)
    await truffleAssert.passes(instance.createKittyGen0(12345, {from:accounts[0]}),truffleAssert.ErrorType.REVERT)
    let owner = await instance.ownerOf(1)
    console.log("Owner of Kitty 1: " + owner)
    let sameOwner = await instance.ownerOf(2)
    console.log("Owner of Kitty 2 : " + sameOwner)
    let result = await instance.balanceOf(owner)
    console.log(result.toNumber())
    assert(owner == accounts[0] && sameOwner == accounts[0] && owner === sameOwner, "Correct Owner not Showing")

  })


})


contract("KittyMarketPlace", async (accounts)=> {
  let otherContractInstance;
  let instance;

  beforeEach(async() => {
    otherContractInstance = await Kittycontract.new();
    instance = await KittyMarketPlace.new(otherContractInstance.address);
    instanceKitty = await Kittycontract.at(instance.address);
  })

  it("Allow Anyone to be able to Transfer Kitty ", async()=> {

    let contract  = await instance._kittyContract;
    console.log("Contract : " + contract);

    //Kittycontract instance functions below
    await truffleAssert.passes(instanceKitty.createKittyGen0(1234, {from:accounts[0]}),truffleAssert.ErrorType.REVERT)
    await truffleAssert.passes(instanceKitty.createKittyGen0(12345, {from:accounts[0]}),truffleAssert.ErrorType.REVERT)
    await truffleAssert.passes(instanceKitty.transfer(accounts[1], 1, {from: accounts[0]}),truffleAssert.ErrorType.REVERT)
    await truffleAssert.passes(instanceKitty.transfer(accounts[1]), 2, {from: accounts[0]},truffleAssert.ErrorType.REVERT)
    await truffleAssert.passes(instanceKitty.transfer(accounts[2],2, {from: accounts[1]}),truffleAssert.ErrorType.REVERT)
    let owner1 = await instanceKitty.ownerOf(1)
    let owner2 = await instanceKitty.ownerOf(2)
    console.log("Owner of Kitty 1 :"  + owner1 + " & Owner of Kitty 2 :" + owner2)
  })

  it("Allow Anyone to be able to Set Operator Approvals of Owned Kitty", async()=> {
    await truffleAssert.passes(instanceKitty.createKittyGen0(1234, {from:accounts[0]}),truffleAssert.ErrorType.REVERT)
    await truffleAssert.passes(instanceKitty.createKittyGen0(12345, {from:accounts[0]}),truffleAssert.ErrorType.REVERT)
    await truffleAssert.passes(instanceKitty.transfer(accounts[1], 1, {from: accounts[0]}),truffleAssert.ErrorType.REVERT)
    await truffleAssert.passes(instanceKitty.transfer(accounts[1], 2, {from: accounts[0]}),truffleAssert.ErrorType.REVERT)
    await truffleAssert.passes(instanceKitty.setApprovalForAll(instance.address, true, {from:accounts[1]}),truffleAssert.ErrorType.REVERT)
    await truffleAssert.passes(instance.setOffer(web3.utils.toWei("2","ether"), 2, {from : instance.address}),truffleAssert.ErrorType.REVERT)
    await truffleAssert.passes(instance.buyKitty(2, {value: web3.utils.toWei("2", "ether"), from: accounts[3]}),truffleAssert.ErrorType.REVERT)

    let owner = await instanceKitty.ownerOf(2)
    console.log('Owner of Kitty 2 which has been recently sold :' + owner)
  })

  it("Allow Anyone to Approve Anyone Else to Set Offer/Get Offer/Sell/Buy Kitty", async() => {
  await truffleAssert.passes(instanceKitty.createKittyGen0(1234, {from:accounts[0]}),truffleAssert.ErrorType.REVERT)
  await truffleAssert.passes(instanceKitty.createKittyGen0(12345, {from:accounts[0]}),truffleAssert.ErrorType.REVERT)
  await truffleAssert.passes(instanceKitty.transfer(accounts[1], 1, {from: accounts[0]}),truffleAssert.ErrorType.REVERT)
  await truffleAssert.passes(instanceKitty.transfer(accounts[1], 2, {from: accounts[0]}),truffleAssert.ErrorType.REVERT)
  await truffleAssert.passes(instanceKitty.approve(accounts[2], 2, {from : accounts[1]}),truffleAssert.ErrorType.REVERT);

  //Now MarketPlace instance functions below:
  await truffleAssert.passes(instance.setOffer(web3.utils.toWei("1","ether"), 1, {from : accounts[1]}),truffleAssert.ErrorType.REVERT)
  await truffleAssert.passes(instance.setOffer(web3.utils.toWei("2","ether"), 2, {from : accounts[2]}),truffleAssert.ErrorType.REVERT)
  let result1 = await instance.getOffer(1)
  let result2 = await instance.getOffer(2)
  console.log("After Testing Offer Details of Kitty 1 are : " + result1 + " & Offer Details of Kitty 2 are : " + result2)
  await instance.buyKitty(1, {value: web3.utils.toWei("1", "ether"), from: accounts[3]})
  await instance.buyKitty(2, {value: web3.utils.toWei("2", "ether"), from: accounts[3]})

  //again testing ownerOf using Kittycontract functions:
  let owner1 = await instanceKitty.ownerOf(1)
  let owner2 = await instanceKitty.ownerOf(2)
  assert(owner1 == accounts[3] && owner2 == accounts[3] && owner === owner1, "Kitty Owner is not correct")
  })

})

So when I ran these tests, I found out that My MarketPlace Functions are all giving Revert (& not passing)
See Below :point_down:
Screenshot 2021-06-18 at 8.07.05 PM
Screenshot 2021-06-18 at 8.18.39 PM

1.So My first Question: Are my Unit Tests Correct ? Am I doing it the right way or my Logic is wrong ?
2. If Correct, then is it that Because MarketPlace functions are Reverting(bcoz of some reason I still havenā€™t figured out) which means the Mappings are not getting Created and hence the marketplace.html page is not showing anything ?
3. Then, why is it that the catalogue.html page is also not showing any Cats, because that is anyways dependent on my index.htmlā€™s createKittie() function ?

Its Really really confusing and I am unable to wrap my Head around it

Below is my Kittycontract.sol and MarketPlace.sol code :point_down:

pragma solidity 0.5.12;
import "./IERC721.sol";
import "./utils/SafeMath.sol";
import "./IERC721Receiver.sol";
import "./Ownable.sol";
import "./ArrayUtils.sol";


contract Kittycontract is IERC721, Ownable {

using SafeMath for uint256;
using ArrayUtils for uint256[];


// constructor
constructor() public {

    _createKitty(0,0, uint256(-1), 0, address(0));
}



//events
event Birth(
  address owner,
  uint256 genes,
  uint256 newKittenId,
  uint256 mumId,
  uint256 dadId);

event Transfer(address indexed oldOwner, address indexed newOwner, uint256 indexed tokenId);
event Approval(address indexed Owner, address indexed approvedTo, uint256 indexed tokenId);
event ApproveAll(address indexed Owner, address operator, bool success);

//Struct- it gets stored in storage on EVM
struct Cat {
    uint256 genes;
    uint64 birthTime;
    uint32 mumId;
    uint32 dadId;
    uint16 generation;
    address owner;
}

//Mappings
//       owner    number of Cats
mapping(address => uint256) public tokenOwnershipCount;
//      tokenId     owner
mapping(uint256 => address) public ownershipCertificate;
// approval mapping
mapping(uint256 => address) private kittyIndexToApprove;
// approval all (operator) mapping
//[MYAADDR][OPERATORADDR] => TRUE/FALSE;
mapping(address => mapping(address => bool)) private _operatorApprovals;
//      Owner      Array of Owner's All Kitty Id's
mapping(address => uint256[]) private _ownersKittyIds;


//State variables
address public contractOwner;
string public constant Name = "MEOW-CATS";
string public constant Symbol = "MEOW";
uint256 private constant CREATION_LIMIT_GEN0 = 500;
uint64 private  gen0Counter = 0;
bytes4 internal constant MAGIC_ERC721_RECEIVED = bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));
bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;

//arrays- stored in storage on EVM
Cat[] public cats;

//##############################################################################################################
//FUNCTIONS START HERE :
//Function when called from external contract returns whether this contract support IERC721 or IERC165 standard?
function supportsInterface(bytes4 _interfaceId) external view returns(bool) {
  return ( _interfaceId == _INTERFACE_ID_ERC165 || _interfaceId == _INTERFACE_ID_ERC721);
}

// SAFE TRANSFER FUNCTIONS
//Function executing an External Call from another User/ Contract(without Data):
function safeTransferFrom(address _from, address _to, uint256 _tokenId) public {
  safeTransferFrom(_from, _to, _tokenId, " ");
}

//Function executing an Public Call which then goes through external Interface(called with @param bytes calldata _data):
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory _data) public {
  require(isApprovedOrOwner(msg.sender, _from, _to, _tokenId), "Neither Approved nor Owner");
  _safeTransfer(_from, _to, _tokenId, _data);
}


//Internal safeTransfer Function
function _safeTransfer(address _from, address _to, uint256 _tokenId, bytes memory _data) internal {
  require( _checkERC721Support(_from, _to, _tokenId, _data) );
  _transfer(_from, _to, _tokenId);
}

//Function executing an External Call from another User/ Contract:
function transferFrom(address _from, address _to, uint256 _tokenId) public {
  require(isApprovedOrOwner(msg.sender, _from, _to, _tokenId), "Not approved or Owner");
  //require(_to != address(0));
  //require(_to != address(this));
  //require(_owns(_from, _tokenId));
  //require(msg.sender == _from || approvedFor(msg.sender, _tokenId) || isApprovedForAll(_from, msg.sender));
  //require(_tokenId < cats.length);
  _transfer(_from, _to, _tokenId);

}

//Function executing an External Call from another User/ Contract:
function transfer(address _to, uint256 _tokenId) public {
  require(_to != address(0), "Cannot transfer to address(0)");
  require(_to != address(this), "Cannot transfer to contract Instance");
  require(_owns(msg.sender, _tokenId), "You are not authorized as you are not Owner");

  _transfer(msg.sender, _to, _tokenId);
}

//Actual transfer of the token happens from this below Internal Function:
function _transfer(address _from, address _to, uint256 _tokenId) internal {
  tokenOwnershipCount[_to]++ ;
  if(_from != address(0)){
    tokenOwnershipCount[_from]-- ;
    _ownersKittyIds[_from].removeFrom(_tokenId);
    delete(kittyIndexToApprove[_tokenId]);
  }
  ownershipCertificate[_tokenId] = _to;
  _ownersKittyIds[_to].push(_tokenId);
  //Event Transfer to be emitted now :
  emit Transfer(_from, _to, _tokenId);
}


//##########################################################################################################



//BASIC CAT CREATION, BREEDING & GETTER FUNCTIONS
function createKittyGen0(uint256 _genes) public onlyOwner returns(uint256){
  require(gen0Counter < CREATION_LIMIT_GEN0);
    gen0Counter ++;

  return _createKitty(0,0, _genes, 0, msg.sender);

}

function breed(uint256 _dadId, uint256 _mumId) public returns(uint256) {
  ( uint256 _dadDna,,,,, uint256 dadGeneration) = getKitty(_dadId);
  ( uint256 _mumDna,,,,, uint256 mumGeneration) = getKitty(_mumId);

  uint256 newDna = _mixDna(_dadDna, _mumDna);

  uint256 kidGen = 0;
  if (dadGeneration < mumGeneration) {
    kidGen = mumGeneration +1;
    kidGen /= 2;
  }
  else if (dadGeneration < mumGeneration) {
    kidGen = dadGeneration +1 ;
    kidGen /= 2;
  }
  else {
    kidGen = mumGeneration + 1;
  }
  _createKitty(_mumId, _dadId, newDna, kidGen, msg.sender);

  // Create the new kitty (with breeder becoming new kitties owner)
  uint256 newKittyId = _createKitty(
      _mumId,
      _dadId,
      kidGen,
      newDna,
      msg.sender
  );
  return newKittyId;
}

function _mixDna(uint256 _dadDna, uint256 _mumDna) internal returns(uint256) {
  //uint256 firstHalf = _dadDna /100000000;
  //uint256 secondhalf = _mumDna % 100000000;
  //uint256 newDna = firstHalf * 100000000;
  //newDna += secondhalf;
  //emit event DNA
  //emit NewDnaCreated(newDna);
  //return newDna;
  uint256[8] memory geneArray;
  uint256 i = 1;// lets say Random number is 11001011
  uint256 index = 7;
  uint8 random = uint8(now % 255);// binary between 00000000-11111111;
  for (i = 1; i <= 128; i = i*2 ){
    if(random & i != 0){
      geneArray[index] = uint8(_mumDna % 100);
    }
    else {
      geneArray[index] = uint8(_dadDna % 100);
    }
    _mumDna = _mumDna / 100;
    _dadDna = _dadDna / 100;
    index = index -1 ;
    //1,2,4,8,16,32,64, 128
    //00000001 - 1
    //00000010 - 2
    //00000100 -  4
    //00001000 - 8
    //00010000 - 16
    //00100000 - 32
    //10000000 - 64
    //10000000 - 128;
    /* if (true && false)
    11001011
    &
    00000001 = 1 // Keep checking all numbers against 11001011
    if(1) then mum _genes
    if(0) then dad _genes */
  }
  uint256 newGene;
  // [ 11, 22, 33, 44,55 ,66, 77, 88]
  for (i = 0; i < 8; i ++) {
    newGene = newGene + geneArray[i];
    if(i != 7) {
      newGene = newGene * 100;
    }
  }
  return newGene;
}


function _createKitty (
  uint256 _mumId,
  uint256 _dadId,
  uint256 _genes,
  uint256 _generation,
  address _owner
) private returns(uint256) {

  Cat memory _cat = Cat({
    genes : _genes,
    birthTime : uint64(now),
    mumId : uint32(_mumId),
    dadId : uint32(_dadId),
    generation : uint16(_generation),
    owner : _owner
  });
  uint256 newKittenId = cats.push(_cat) - 1;

  //Event Birth to  be emitted :
  emit Birth(_owner, _genes, newKittenId, _mumId, _dadId);

  _transfer(address(0), _owner, newKittenId);
  return newKittenId;
}


function getKitty(uint256 _newKittenId) public view returns(
uint256 _genes,
uint256 _mumId,
uint256 _dadId,
uint256 _birthTime,
address _owner,
uint256 _generation){

  Cat storage cat = cats[_newKittenId];
  _genes = cat.genes;
  _dadId = uint256(cat.dadId);
  _mumId = uint256(cat.mumId);
  _generation = uint256(cat.generation);
  _birthTime = uint256(cat.birthTime);
  _owner = cat.owner;

}

function getKittyByOwner(address _owner) external view returns(uint[] memory) {
  /**uint[] memory result = new uint[](tokenOwnershipCount[_owner]);
  uint counter = 0;
  for (uint i = 0; i < cats.length; i ++) {
    if (ownershipCertificate[i] == _owner) {
      result[counter] = i;
      counter ++;
    }
  }
  return result;*/
  // Set pointer to owners array of kitty Ids
  return _ownersKittyIds[msg.sender];
}

function balanceOf(address owner) external view returns (uint256 balance) {
  return tokenOwnershipCount[owner];
}

function totalSupply() public view returns (uint256 total) {
  total = cats.length;
  return total;
}

function name() external view returns (string memory tokenName) {
  tokenName = Name;
  return tokenName;
}


function symbol() external view returns (string memory tokenSymbol) {
  tokenSymbol = Symbol;
  return tokenSymbol;
}

function ownerOf(uint256 tokenId) external view returns (address owner) {
  return ownershipCertificate[tokenId];
}



//This below Function called "_owns" gives bool result whether the address has actual ownership of the _tokenId:
function _owns(address _claimant, uint256 _tokenId) internal view returns(bool) {
  return ownershipCertificate[_tokenId] == _claimant;
}



// APPROVE FUNCTION & GETTER FUNCTIONS RELATED TO APPROVALS :

function approve(address to, uint256 tokenId) public {
  require(_owns(msg.sender, tokenId));
  _approve(to, tokenId);
}

function _approve(address _approved, uint _tokenId ) internal {
  _approved = kittyIndexToApprove[_tokenId];
  //emit event Approve
  emit Approval(msg.sender, _approved, _tokenId);

}

function getApproved(uint256 _tokenId) public view returns (address) {
  require(_tokenId < cats.length); //Token must exist
  return kittyIndexToApprove[_tokenId];
}

function setApprovalForAll(address operator, bool approved) public {
  require(operator != msg.sender, "Operator cannot be msg.sender");
  _setApprovalForAll(msg.sender, operator, approved);
}

function _setApprovalForAll(address _owner, address _operator, bool _approved) internal {
  _approved = _operatorApprovals[_owner][_operator];
  //emit event ApproveAll
  emit ApproveAll(msg.sender, _operator, _approved);
}


function isApprovedFor(address _claimant, uint256 _tokenId) internal view returns(bool) {
  return kittyIndexToApprove[_tokenId] == _claimant;
}


function isApprovedForAll(address _owner, address _operator) public view returns (bool) {
  return _operatorApprovals[_owner][_operator];
}

function isApprovedOrOwner(address _spender, address _from, address _to, uint256 _tokenId) internal view returns(bool) {
  require(_to != address(0));
  require(_to != address(this));
  require(_owns(_from, _tokenId));
  require(_tokenId < cats.length);
  return (_spender == _from || isApprovedFor(_spender, _tokenId) || isApprovedForAll(_from, _spender));
}

//#######################################################################################################

// INTERNAL FUNCTION ASKING FOR ERC 721 SUPPORT  :
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 on onERC721Received in the _to contract
  return returnData == MAGIC_ERC721_RECEIVED;
  // Check on Return Value;
}

// IF SIZE = O =>ITS A USER WALLET, IF > 0 => ITS A CONTRACT :
function _isContract(address _to) internal view returns(bool) {
  uint32 size;
  assembly{
    size := extcodesize(_to)
  }
  return size > 0;
}


}
pragma solidity 0.5.12;

import "./Kittycontract.sol";
import "./IKittyMarketPlace.sol";
import "./utils/SafeMath.sol";
import "./Ownable.sol";


contract KittyMarketPlace is IKittyMarketPlace, Ownable {

  using SafeMath for uint256;



  Kittycontract public _kittyContract;

//events
event MarketTransaction(string TxType, address owner, uint256 tokenId);

//Struct with Offer Details of the MarketPlace web app:
  struct Offer {
    address payable seller;
    uint256 price;
    uint256 index;
    uint256 tokenId;
    bool active;
  }

//Mapping tokenId =>  struct
mapping (uint256 => Offer) tokenIdToOffer;

//Offer array of available Offers;
Offer[] offers;

//Constructor :
constructor(address kittyContractAddress) public {
  setKittyContract(kittyContractAddress);
}

function setKittyContract(address kittyContractAddress)
public onlyOwner {
  _kittyContract = Kittycontract(kittyContractAddress);
}


function getOffer(uint256 _tokenId) public view returns
(
  address seller,
  uint256 price,
  uint256 index,
  uint256 tokenId,
  bool active
) {

  require(_isOnOffer(_tokenId) == true, "There is No Active Offer for this Cat");
  require(tokenIdToOffer[_tokenId].seller != address(0), "Token not on offer!");

/** Below is One Method of assigning variables to Mappingwhich point to a Struct
  seller = tokenIdToOffer[_tokenId].seller;
  price = tokenIdToOffer[_tokenId].price;
  index = tokenIdToOffer[_tokenId].index;
  tokenId = tokenIdToOffer[_tokenId].tokenId;
  active = tokenIdToOffer[_tokenId].active;
*/
  //another way of doing it (assigning directly to Struct + Mapping) is like below :

Offer storage offer = tokenIdToOffer[_tokenId];
return (
  offer.seller,
  offer.price,
  offer.index,
  offer.tokenId,
  offer.active
);

}


function setOffer(uint256 _price, uint256 _tokenId) external {
  require(_isKittyOwner(msg.sender, _tokenId), "You are not the owner of this Cat");
  require(_isOnOffer(_tokenId) == false, "There is already an Active Offer for this Cat so You cannot sell the same Token twice");
  require(_kittyContract.isApprovedForAll(msg.sender, address(this)), "MarketPlace Contract needs to be authorized for selling Kitty in the Future");

Offer memory newOffer = Offer({
  seller : msg.sender,
  price : _price,
  tokenId : _tokenId,
  index : offers.length,
  active : true

});

 offers.push(newOffer);
 tokenIdToOffer[_tokenId] = newOffer;

//Emit Event MarketTransaction
emit MarketTransaction("Create Offer", msg.sender, _tokenId);
}


function getAllTokenOnSale() external view  returns(uint256[] memory ) {

  uint256 totalOffers = offers.length;
// Filip's way:
  /**if (totalOffers == 0) {
   return new uint256[](0);//SIZE 1,2,3,4,5,
  }
 else {
*/
  uint256[] memory allOfferIds = new uint256[](totalOffers);
  uint256 i;
  uint256 activeOffers = 0;
  for (i = 0; i < totalOffers; i++) {
    if (offers[i].active == true) {
      allOfferIds[activeOffers] = offers[i].tokenId;
      activeOffers = activeOffers.add(1);
    }
  }

  if (activeOffers == totalOffers) return allOfferIds;

  //Else return a correctly sized array of only Active offers
  uint256[] memory activeOfferIds = new uint[](activeOffers);
  for (i = 0; i < activeOffers; i++ ) {
    activeOfferIds[i] = allOfferIds[i];
  }
return activeOfferIds;

//Continuation of Filip's way :
  /**uint256[] memory result = new uint256[](totalOffers);
  uint256 offerId;

  for (offerId = 0; offerId < totalOffers; offerId ++) {
    if(offers[offerId].active == true) {
      result[offerId] = offers[offerId].tokenId;
    }
  }

  return result;

}*/
}



function removeOffer(uint256 _tokenId) external {
  require(_isOnOffer(_tokenId) == true, "There is No Active Offer against this Cat");
  require(msg.sender == tokenIdToOffer[_tokenId].seller, "Only Seller can Remove Offer");

  _removeOffer(_tokenId);
  // or We can use below two lines of code to ensure that the Offer is removed both from the Offer mapping i.e tokenIdToOffer and also from the offers array
  //delete(tokenIdToOffer[_tokenId]);
  //offers[tokenIdToOffer[_tokenId].index].active = false;


  //Emit Market Transaction event
  emit MarketTransaction("Remove Offer", msg.sender, _tokenId);
}



function buyKitty(uint256 _tokenId) external payable {
  Offer memory offer = tokenIdToOffer[_tokenId];
  require(_isOnOffer(_tokenId) == true, "This Cat is not for sale as there is No Active Offer against this");
  require(msg.value >= offer.price, "Please send Full Token Price");

  // Delete the Mapping of the Tranferrable token
  // Set the Bool= active as false in the Offer array as well
  //delete(tokenIdToOffer[_tokenId]);
  //offers[offer.index].active = false;
  _removeOffer(_tokenId);
  //transfer of the price to the seller
  //PUSH METHOD
  //if (offer.price > 0) {
    //offer.seller.transfer(offer.price);
  //IMPLEMENTED PULL METHOD AS BELOW
  if(msg.value > 0) {
    (bool success, ) = offer.seller.call.value(msg.value)("");
    require(success, "Payment to seller failed!");
    }

  //Finally transfer the Ownership of the Kitty using the transferFrom function in KittyContract:
  _kittyContract.safeTransferFrom(offer.seller, msg.sender, _tokenId);

  //Emit MarketTransaction event
  emit MarketTransaction("Buy", msg.sender, _tokenId);
}


function _isKittyOwner(address claimant,uint256 tokenId)
    internal
    view
    returns (bool)
{
    return(_kittyContract.ownerOf(tokenId) == claimant);
}


function _isOnOffer(uint256 tokenId) internal view returns (bool) {
    return(tokenIdToOffer[tokenId].active == true);
}


/* External Function:
** Checks if given tokenId is on sale or not; returning true if it is, false if not.
*/
function isTokenOnSale(uint256 tokenId) external view returns (bool) {
    return (_isOnOffer(tokenId));
}


function _removeOffer(uint256 tokenId) internal {
    Offer memory toBeRemoved = tokenIdToOffer[tokenId];

    uint256 lastIndex = offers.length.sub(1);
    if (toBeRemoved.index < lastIndex) { // not the last offer in the array
        // Move last offer record (in array) to overwrite the offer to be removed
        Offer memory lastOffer = offers[lastIndex];
        lastOffer.index = toBeRemoved.index;       // poisition to which last offer record will be moved
        offers[toBeRemoved.index] = lastOffer;    // overwrite offer to be removed (with last offer record)
        tokenIdToOffer[lastOffer.tokenId] = lastOffer; // Update record in the token mapping
        }
    offers.pop();   // remove last offer record (now redundant as moved, or is the offer to be removed)
    delete tokenIdToOffer[toBeRemoved.tokenId];
    }




}

I am struggling so much ( although I am learning a lot too), but I really need your help :pray:

About your question :point_down:
Hi @Su.kal.Crypto please send me the errors about the market place or just show me the way you are rendering the cats.

The marketplace.html and catalogue.html , both pages are not showing any errors, but I cannot see the Cats on the page even after the createKittie() function is executed by accounts[0], i.e Owner

Still, if you want this has all the files of the full code :point_down:
https://github.com/Suveett/CryptoKitties.git
This is how the Marketplace.html and catalogue.html pages look like after creating 3 kitties :point_down:
Screenshot 2021-06-18 at 9.30.23 PM
Screenshot 2021-06-18 at 9.30.37 PM

Thanks and awaiting your Revert

Suveett Kalra (Su.Kal Crypto)

Helloo :slight_smile:

So, I was playing with the frontend (more to say implementing Filipā€™s breeding frontend), when I realized that I messed up my Create Kitty button.
For the last few hours I am trying to figure it out, but nothing.
It was working properly until today, now I just get this in the console when I hit the create kitty button:
Screenshot 2021-06-21 at 02.19.17

I checked the index.js many times, but everything seems ok to my eyes :smiley:

I would really appreciate if someone helps me out with this setback :frowning:

The full code can be found here:
https://github.com/margaritavas/CryptoKitty-Clone.git

Thank you :slight_smile:

Is your ganache or local testnet run it properly?

Carlos Z

Hi Carlos,

I believe it is, since I had no problems previously.
I restarted ganache once again just in case, checked the account in metamask, updated the contract address in index.js but it still shows the same error in the console.

Edit:

Found it!:tired_face:
When declaring web3, I used a small w instead of a capital one. :grinning:

1 Like

Iā€™m STUCK on this: how do you get a return value from a solidity function to the javascript client. Iā€™ve tried almost everything and researched online and cannot crack it. (some people online say itā€™s not possible!)

see hereā€¦

  // returns total number of cats created in Kitty smart contact
  async function TotalCats() {


    let totalCat = await instance.methods.totalSupply().call();

    console.log("total inside: " + totalCat);
    return totalCat;

}

the console.log returns the right value, but when i do ā€œvar totalCats = TotalCats()ā€ I get a promise back.

And yes i did try .then(function(){}), that returned the same results. A promise.

The promise results has the correct value. However how do I extract the promise results into a javascript variable (var totalCats in this example)??

This is SO easy to do on Truffle console, and with test harnesses ( .it ). Why is it so hard when youā€™re actually creating an application? uffff!

hey @apmfree if you want a variable to assign the value you have to await for that value:

var totalCats = await TotalCats();

This is easy right? the problem here is that even when you assign it, will not be always available since is a promise you have to also use straight away or place it where you want.

Optionally you can use the value inside the totalCats() function. This will always work if you apply changes insisde the function logic.

function TotalCats() {

    let totalCat = await instance.methods.totalSupply().call();
    //For example
   document.getElementById("totalcats").innerHTML  =  totalCat;

}

Having serious issue with web3 ā€¦ see code snippet belowā€¦

$(document).ready(function() {
    window.ethereum.enable().then(function(accounts) {
        instance = new web3.eth.Contract(abi,"0x5f78916B261813f9650d47A4f0f90FCB007C9c41", {from: accounts[0]});
        user = accounts[0];
        console.log(instance);

        //get promise for total # of cats
        var totalCatPromise = instance.methods.totalSupply().call();
        console.log(totalCatPromise);
        var testPromises = instance.methods.getKitty(0).call();
        console.log(testPromises);
        
        Promise.all([totalCatPromise]).then(values => {
            totalCats = values[0];

For this lineā€¦

  var testPromises = instance.methods.getKitty(0).call();

Keep getting "catalogue.js:18 Uncaught (in promise) TypeError: instance.methods.getKitty is not a function"

I scoured the internet to no avail. Stuck on this. And yes i double , triple checked the ABI. It does include getKitty. getkiddy is public view function in kitty contract.

Also, I checked the output of ā€œconsole.log(instance);ā€ and it clearly shows getKitty under methods.

As a comparison ā€œvar totalCatPromise = instance.methods.totalSupply().call();ā€ works perfectly with no issues.

Replaced the ABI. Tried everything. Even tried downgrading version of web3 from 1.4 to 1.3. Still does not work.

Any idea what I may be doing wrong???

hi kenn.eth

Thanks this is helpful!

I also discovered this:

 Promise.all([totalCatPromise]).then(values => {
            totalCats = values[0]; });

This seems to work, however I can only access totalCats within the Promise.all structure.

Is it ok to do it this way?

1 Like