I have this error:
.../node_modules/truffle-expect/index.js:3
expected_keys.forEach(function(key) {
^
Error: Expected parameter 'solc' not passed to function.
when I try to use truffle-solidity-loader using webpack. Any idea how to fix it? Thank you.
UPDATE:
The smart contract:
pragma solidity ^0.5.0;
contract ToDo {
struct Task {
uint id;
uint date;
string content;
string author;
bool done;
}
uint lastTaskId;
mapping(uint => Task) tasks;
uint[] taskIds;
constructor () public{
lastTaskId = 0;
}
event TaskCreated(uint id, uint date, string content, string author, bool done);
function createTask(string memory _content, string memory _author) public {
lastTaskId++;
tasks[lastTaskId] = Task(lastTaskId, now, _content, _author, false);
taskIds.push(lastTaskId);
emit TaskCreated(lastTaskId, now, _content, _author, false);
}
function getTask(uint id) taskExists(id) public view returns (uint, uint, string memory, string memory, bool) {
return(
id,
tasks[id].date,
tasks[id].content,
tasks[id].author,
tasks[id].done
);
}
function getTaskIds() view public returns (uint[] memory) {
return taskIds;
}
// function getTaskFixtures(uint _id) public view returns(uint,uint,string,string,bool) {
// return (0, now, "Create more tutorials for ETB", "Julien", false);
// }
modifier taskExists(uint id){
if(tasks[id].id == 0){
revert();
}
_;
}
}
The index.js:
import artifact from '../../contracts/ToDo.sol';
import Web3 from 'web3';
import TruffleContract from 'truffle-contract';
// import config from './config.js';
console.log('loaded');
const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545'));
const abstraction = new TruffleContract(artifact);
abstraction.setProvider(web3.currentProvider);
const network = Object.keys(artifact.networks)[0];
const address = artifact.networks[network].address;
abstraction.at(address)
.then((todo) => {
todo.getTaskIds()
.then((taskIds) => {
console.log(taskIds);
});
});
web3.eth.getAccounts(console.log);
The server:
const express = require('express');
const app = express();
const PORT = 3000;
//Serve static assets (js, css, ...)
app.use(express.static('app'));
//Serve contract artifact files (ex: ToDo.json)
app.use(express.static('build/contracts'));
//Serve index.html
app.get('/', (req, res) => {
res.sendFile(`${__dirname}/app/index.html`);
});
//If anything else is requested that's an error
app.get('*', (req, res) => {
res.status(404);
res.send('Oops... this URL does not exist');
});
//Start the server
app.listen(PORT, () => {
console.log(`ETB Ethereum ToDo List App running on port ${PORT}...`);
});
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Related
VS Code suggested i install Solidity extension which I did. immediately it installed it required that I update my solidity to 0.8.17; I did then I had to update some parts of the code. after I did, I tested on remix and it worked. Back on vs code now and I've been trying to compile but it is not compiling.It creates the 'build' folder but doesn't write any JSON files in it.
Campaign.sol file:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
contract CampaignFactory {
address[] public deployedCampaigns;
function createCampaign(uint minimum) public {
Campaign newCampaign = new Campaign(minimum, msg.sender);
deployedCampaigns.push(address(newCampaign));
}
function getDeployedCampaigns() public view returns (address[] memory) {
return deployedCampaigns;
}
}
contract Campaign {
struct Request {
string description;
uint value;
address payable recipient;
bool complete;
uint approvalCount;
mapping(address => bool) approvals;
}
Request[] public requests;
address public manager;
uint public minimumContribution;
mapping(address => bool) public approvers;
uint public approversCount;
modifier restricted() {
require(msg.sender == manager);
_;
}
constructor (uint minimum, address creator) {
manager = creator;
minimumContribution = minimum;
}
function contribute() public payable {
require(msg.value > minimumContribution);
approvers[msg.sender] = true;
approversCount++;
}
function createRequest(string memory description, uint value, address payable recipient) public restricted {
Request storage newRequest = requests.push();
newRequest.description = description;
newRequest.value = value;
newRequest.recipient = recipient;
newRequest.complete = false;
newRequest.approvalCount = 0;
}
function approveRequest(uint index) public {
Request storage request = requests[index];
require(approvers[msg.sender]);
require(!request.approvals[msg.sender]);
request.approvals[msg.sender] = true;
request.approvalCount++;
}
function finalizeRequest(uint index) public restricted {
Request storage request = requests[index];
require(request.approvalCount > (approversCount / 2));
require(!request.complete);
request.recipient.transfer(request.value);
request.complete = true;
}
function getSummary() public view returns (
uint, uint, uint, uint, address
) {
return(
minimumContribution,
address(this).balance,
requests.length,
approversCount,
manager
);
}
function getRequestsCount() public view returns (uint) {
return requests.length;
}
}
compile.js file
const path = require("path");
const solc = require("solc");
const fs = require("fs-extra");
const buildPath = path.resolve(__dirname, "build");
fs.removeSync(buildPath);
const campaignPath = path.resolve(__dirname, "contracts", "Campaign.sol");
const source = fs.readFileSync(campaignPath, "utf8");
const output = solc.compile(source, 1).contracts;
fs.ensureDirSync(buildPath);
for (let contract in output) {
fs.outputJsonSync(
path.resolve(buildPath, contract.replace(":", "") + ".json"),
output[contract]
);
}
i'm learning blockchain dev and now i'm trying to mint an NFT, the process is ok but the problem is that metadata are not showed in the wallet or opensea.
This is the contract
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;
import '#openzeppelin/contracts/token/ERC721/ERC721.sol';
import '#openzeppelin/contracts/access/Ownable.sol';
import "#openzeppelin/contracts/utils/Counters.sol";
contract NFT is ERC721, Ownable {
uint256 public mintPrice;
uint256 public maxPerWallet;
uint256 public totalSupply;
bool public isPublicMintEnabled;
string internal baseTokenUri;
address payable public withdrawWallet;
mapping (address => uint256) public walletMints;
mapping(uint256 => string) private _tokenURIs;
Counters.Counter private _tokenIds;
using Counters for Counters.Counter;
using Strings for uint256;
constructor() payable ERC721('NFT', 'NFT') {
mintPrice = 0.0004 ether;
maxPerWallet = 3;
// Set withdraw wallet address
}
function setIsPublicMintEnabled(bool isPublicMintEnabled_) external onlyOwner {
isPublicMintEnabled = isPublicMintEnabled_;
}
function setBaseTokenUri(string calldata baseTokenUri_) external onlyOwner {
baseTokenUri = baseTokenUri_;
}
function tokenURI(uint256 tokenId_) public view override returns (string memory) {
require(_exists(tokenId_), 'Token does not exist!');
return string(abi.encodePacked(baseTokenUri, Strings.toString(tokenId_), ".json"));
}
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual
{
_tokenURIs[tokenId] = _tokenURI;
}
function withDraw() external onlyOwner {
(bool success, ) = withdrawWallet.call{ value: address(this).balance } ('');
require(success, 'Withdraw failed');
}
function mint(string memory uri) public payable returns (uint256) {
require(isPublicMintEnabled, 'Mint is not enabled');
require(msg.value == mintPrice, 'Wrong mint value');
require(walletMints[msg.sender] + 1 <= maxPerWallet, 'Exceed max quantity per wallet');
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(msg.sender, newItemId);
_setTokenURI(newItemId, uri);
return newItemId;
}
}
And this is the mint function on the mint website
const mintNFT = async (nft) => {
setMinting(true)
const mintAmount = 1
const isConnected = Boolean(accounts[0])
if (!isConnected) {
alert('Non sei connesso al tuo Wallet')
setMinting(false)
return
}
var nftParsed = JSON.parse(nft.metadata)
if (window.ethereum) {
// Connect to blockchain
const provider = new providers.Web3Provider(window.ethereum)
const signer = provider.getSigner()
const contract = new Contract(
address,
NFT.abi, // Implement
signer
)
const imageFile = await dataUrlToFile(nftParsed.image, "img.png")
const nftstorage = new NFTStorage({ token: NFT_STORAGE_KEY })
const storage = await nftstorage.store({
image: imageFile,
name: nftParsed.name,
description: 'prova'
})
if (storage) {
try {
const response = await contract.mint(storage.url, {
value: ethers.utils.parseEther((0.0004).toString())
})
console.log(response)
} catch (e) {
console.error(e)
alert("Sorry, error while minting your NFT")
setMinting(false)
}
} else {
alert("Mint problems")
setMinting(false)
}
setMinting(false)
}
}
This code convert dataurl (format for nft saved in db) to image
async function dataUrlToFile(dataUrl, fileName) {
const res = await fetch(dataUrl);
const blob = await res.blob();
return new File([blob], fileName, { type: 'image/png' });
}
In first try, i successfully created nft with metadata, but now using a min website seems to be impossible, the time that it worked the image was stored in a directory and not in a dataurl format.
Hope someone can help,
Thanks
after I run command truffle test
I got this error
TypeError: _character.getName is not a function
my test file
let Game = artifacts.require("./Game.sol");
let Character = artifacts.require("./Character.sol");
const PROVIDED_NAME = "TEST";
contract("Game", (accounts) => {
let creatorAccount = accounts[0];
it("should create a character with the name provided", () => {
let _game;
let _character;
return Game.deployed()
.then(instance => {
_game = instance;
return _game.createCharacter(PROVIDED_NAME, { from: creatorAccount });
})
.then(result => {
return _game.getCharacter();
})
.then(character => {
_character = Character.at(character);
return _character.getName();
})
.then(name => {
assert.equal(name, PROVIDED_NAME, "Failed to create a character with the provided name");
});
});
});
and this my Character.sol file
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
contract Character {
string private _name;
constructor(string memory name) public {
_name = name;
}
function getName() public view returns (string memory) {
return _name;
}
}
I'm using
Truffle v5.5.20 (core: 5.5.20)
Ganache v7.2.0
Solidity - 0.8.15 (solc-js)
Node v16.15.1
Web3.js v1.7.4
I think the issue is with the way how you require them. you should not pass the directory path, instead pass the name of the contracts, truffle will assign them.
let Game = artifacts.require("NameOfGamecontract");
let Character = artifacts.require("NameOfCharacterContract");
I want to do some integration test skiping the last part of my endpoints when a class that I code (using sdk library), get data from a third party API. So my test case is the following:
describe('GET /getCustomer/:id', ()=>{
describe('get customer with id 1: ',()=>{
it('should respond success message', (done) => {
chai.request(app)
.get('/api/getCustomer/customerIDsample')
.end( function(err,res){
expect(res).to.have.status(SUCCESS);
done();
});
});
});
});
my Express NodeJS API works as:
route -> controller (req,res) -> service (my logic) -> gateway/client.
So the module that I need to stub is gateway/client. Let me show you the endpoint path from start to Client class:
route.js:
router.get('/getCustomer/:id', CustomerController.getCustomer
);
controller.js:
'use strict';
const { UNPROCESSABLE_ENTITY, SUCCESS, INTERNAL_SERVER_ERROR } = require('../../constants/httpCodes');
const CustomerService = require('../../services/customerService');
class CustomerController {
static async getCustomer (req, res) {
const customerID = req.params.id;
const customerService = new CustomerService(customerID);
try {
const getCustomer = await customerService.getCustomer()
return res.status(SUCCESS).send(getCustomer);
} catch (error) {
return res.status(INTERNAL_SERVER_ERROR).send({
"details": error
});
}
}
}
service.js:
'use strict';
const validate = require('jsonschema').validate;
const Client = require('../gateways/Client')
const ClientCustomerSchema = require('../schemas/ClientCustomerSchema');
class CustomerService {
constructor(customer) {
this.customer = customer;
}
async getCustomer() {
const client = new Client(this.customer);
try {
const newCustomer = await client.getCustomer();
return newCustomer;
} catch (error) {
throw error
}
}
}
client.js: this is my class to wrap an SDK from a API similar than paypal, Client is a fantasy name:
'use strict';
const Client = require('Client');
const { client } = require('../config/index');
class openPayClient {
constructor(customer) {
this.customer = customer;
this.client = new Client(
client.ID,
client.PRIVATE_KEY
);
}
async getCustomer() {
return await new Promise((resolve, reject) => {
this.client.customers.get(this.customer, function(error, body) {
if(error) {
reject(error)
} else {
resolve(body)
}
});
});
}
Of course I did researching but I found anything regarding stub classes in this kind of scenarios when actually you are not using the function/class explicitly in the test file. The module that I need to stub is Client.js, because this one use client.customer.get method that calls an external API through sdk library.
I am a beginner in blockchain programming and I am not able to understand why I am getting an error while trying to solidity function using Web3 and Ganache.
const PetList = require('./build/contracts/PetList.json')
const fs = require('fs')
const Web3 = require('web3')
const abi = fs.readFileSync("build/contracts/PetList.json").toString().trim();
// Ganache Blockchain
const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545"));
web3.eth.net.isListening()
.then(() => console.log('Web3 is connected'))
.catch(e => console.log('Wow. Something went wrong'));
var setUpContract = async function( ){
await web3.eth.net.getId().then((networkId) => {
const networkData = PetList.networks[networkId]
console.log("Setting up contract...")
if(networkData){
return petList = new web3.eth.Contract(PetList.abi, networkData.address)
}
})
acc = await web3.eth.getAccounts()
currentAccount = acc[0]
console.log("Account: ", acc[0])
}
async function start(){
await setUpContract()
await addPet()
}
var addPet = async function(){
console.log(await getPetCount())
return results = await petList.methods.addPet('Zippo', 'Dog').send({from: currectAccount})
}
start()
pragma solidity ^0.5.0;
contract PetList{
uint public petCount = 0;
mapping (uint => Pet) public pets;
struct Pet{
uint id;
string name;
string tag;
}
event PetAdded(
uint id,
string name,
string tag
);
function addPet(string memory _name, string memory _tag) public {
require(bytes(_name).length > 0, "INVALID TAG");
require(bytes(_tag).length > 0, "INVALID NAME");
petCount++;
pets[petCount] = Pet(petCount, _name, _tag);
emit PetAdded(petCount, _name, _tag);
}
}
I also used .send() without any parameters and it gave me an error saying No "from" address specified in neither the given options, nor the default options.
To make a function receive ether you must have a fallback function or add payable modifier
So you can change your code to the following
function addPet(string memory _name, string memory _tag) public payable