I'm running a truffle project created with truffle init command in CMD. then I create a react app with npx reate-react-app in the same folder.
I'm creating a NFT so I have installed OZ contracts in my react app with using npm install #openzeppelin/contracts command.
Now at this point whole project looks like this.
root folder
Package.json
and this is the complete truffle-config.js
/**
* Use this file to configure your truffle project. It's seeded with some
* common settings for different networks and features like migrations,
* compilation and testing. Uncomment the ones you need or modify
* them to suit your project as necessary.
*
* More information about configuration can be found at:
*
* trufflesuite.com/docs/advanced/configuration
*
* To deploy via Infura you'll need a wallet provider (like #truffle/hdwallet-provider)
* to sign your transactions before they're sent to a remote public node. Infura accounts
* are available for free at: infura.io/register.
*
* You'll also need a mnemonic - the twelve word phrase the wallet uses to generate
* public/private key pairs. If you're publishing your code to GitHub make sure you load this
* phrase from a file you've .gitignored so it doesn't accidentally become public.
*
*/
// const HDWalletProvider = require('#truffle/hdwallet-provider');
// const infuraKey = "fj4jll3k.....";
//
// const fs = require('fs');
// const mnemonic = fs.readFileSync(".secret").toString().trim();
const path = require("path");
module.exports = {
contracts_build_directory: path.join(__dirname, "client/src/contracts"),
/**
* Networks define how you connect to your ethereum client and let you set the
* defaults web3 uses to send transactions. If you don't specify one truffle
* will spin up a development blockchain for you on port 9545 when you
* run `develop` or `test`. You can ask a truffle command to use a specific
* network from the command line, e.g
*
* $ truffle test --network <network-name>
*/
networks: {
// Useful for testing. The `development` name is special - truffle uses it by default
// if it's defined here and no other network is specified at the command line.
// You should run a client (like ganache-cli, geth or parity) in a separate terminal
// tab if you use this network and you must also set the `host`, `port` and `network_id`
// options below to some value.
//
development: {
host: "127.0.0.1", // Localhost (default: none)
port: 7545, // Standard Ethereum port (default: none)
network_id: "*", // Any network (default: none)
},
// Another network with more advanced options...
// advanced: {
// port: 8777, // Custom port
// network_id: 1342, // Custom network
// gas: 8500000, // Gas sent with each transaction (default: ~6700000)
// gasPrice: 20000000000, // 20 gwei (in wei) (default: 100 gwei)
// from: <address>, // Account to send txs from (default: accounts[0])
// websocket: true // Enable EventEmitter interface for web3 (default: false)
// },
// Useful for deploying to a public network.
// NB: It's important to wrap the provider as a function.
// ropsten: {
// provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`),
// network_id: 3, // Ropsten's id
// gas: 5500000, // Ropsten has a lower block limit than mainnet
// confirmations: 2, // # of confs to wait between deployments. (default: 0)
// timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50)
// skipDryRun: true // Skip dry run before migrations? (default: false for public nets )
// },
// Useful for private networks
// private: {
// provider: () => new HDWalletProvider(mnemonic, `https://network.io`),
// network_id: 2111, // This network is yours, in the cloud.
// production: true // Treats this network as if it was a public net. (default: false)
// }
},
// Set default mocha options here, use special reporters etc.
mocha: {
// timeout: 100000
},
// Configure your compilers
compilers: {
solc: {
version: "0.6.1", // Fetch exact version from solc-bin (default: truffle's version)
// docker: true, // Use "0.5.1" you've installed locally with docker (default: false)
// settings: { // See the solidity docs for advice about optimization and evmVersion
// optimizer: {
// enabled: false,
// runs: 200
// },
// evmVersion: "byzantium"
// }
}
},
// Truffle DB is currently disabled by default; to enable it, change enabled: false to enabled: true
//
// Note: if you migrated your contracts prior to enabling this field in your Truffle project and want
// those previously migrated contracts available in the .db directory, you will need to run the following:
// $ truffle migrate --reset --compile-all
db: {
enabled: false
}
};
in my solidity contract file, path is C:\Dapp\Pet-Shop-IPFS-React\contracts\PetShop.sol, I've imported the installed OZ ERC721 contract
PetShop.js
pragma solidity >=0.4.22 <0.9.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
contract PetShop is ERC721 {
uint256 public tokenId;
uint256 public prevOwnerTokenID;
address public owner;
mapping(uint256 => uint256) public priceMapping;
mapping(uint256 => string) tokenIdToOffchainContentHash;
event PetGenerated(address, uint256, uint256, string);
event BuyPet(uint256, address, address);
event SuccessfulEtherWithdrawal(uint256, address, bool);
constructor()
ERC721("ShanBuilders", "SBRS")
{
owner = msg.sender;
}
function generatePet(uint256 _petPrice, string memory contentHash) public returns(bool) {
require(msg.sender != address(0), "Please! Check back! Registeration should not be from zero address");
require(msg.sender == owner, "Only contract owner can generate more pets");
tokenId++;
require(tokenId <= 16, "More than 16 pets is not allowed");
priceMapping[tokenId] = _petPrice;
tokenIdToOffchainContentHash[tokenId] = contentHash;
_mint(owner, tokenId);
emit PetGenerated(owner, tokenId, _petPrice, contentHash);
return true;
}
function checkPrice(uint256 _tokenId) public view returns(uint256) {
return priceMapping[_tokenId];
}
function checkHashForAToken(uint256 _tokenId) public view returns(string memory) {
return tokenIdToOffchainContentHash[_tokenId];
}
function buyPet(uint256 _tokenId) public payable returns(bool, string memory) {
prevOwnerTokenID = _tokenId;
address buyer = msg.sender;
address _owner = ownerOf(prevOwnerTokenID);
require(buyer != address(0), "Should not be zero address");
require(_exists(prevOwnerTokenID), "Invalid property Id, not registered");
require(msg.value == checkPrice(prevOwnerTokenID), "Please Send The Required Value");
withDraw(msg.value);
_transfer(_owner, buyer, prevOwnerTokenID);
emit BuyPet(_tokenId, _owner, buyer);
return (true, "Succesful");
}
function withDraw(uint256 _amount) internal returns(bool) {
address _owner = ownerOf(prevOwnerTokenID);
require(_amount > 0, "Amount must be valid");
payable(_owner).transfer(_amount);
emit SuccessfulEtherWithdrawal(_amount, _owner, true);
return true;
}
}
this is Migration
const PetShop = artifacts.require("PetShop");
module.exports = function (deployer) {
deployer.deploy(PetShop);
};
Q is after doing all this something went wrong that I didn't notice. when i run truffle compile it fails the compilation and throws error,
*** ParserError: Source "#openzeppelin/contracts/token/ERC721/ERC721.sol" not found: File import callback not supported***
How can I work around this issue, It will be great if someone could help me understand what this error says and why this is happening?
I have solved it in the following way,
#openzeppelin library. i installed it in the wrong place, in react, it should have been installed in the root folder, after installing #openzeppelin in root folder, it creates package-lock.json
compiler version as #openzeppelin's contracts using latest solidity version every time, for now it is 0.8.0, and the truffle current version was 5.2.0, and truffle using solidity version 0.5.0 or something between to 0.5.5, what did i do first install npm install solc#0.8.0 in root folder it updates package-lock.json like this
"solc": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/solc/-/solc-0.8.0.tgz",
"integrity": "sha512-ypgvqYZhb/i5BM6cw9/5QkSlDJm/rLynsbWGP3kz6HeB6oNxPK6UMiB7jMr+tNVbQbBM/8l47vrI3XaDCHShjQ==",
"requires": {
"command-exists": "^1.2.8",
"commander": "3.0.2",
"follow-redirects": "^1.12.1",
"fs-extra": "^0.30.0",
"js-sha3": "0.8.0",
"memorystream": "^0.3.1",
"require-from-string": "^2.0.0",
"semver": "^5.5.0",
"tmp": "0.0.33"
}
then update truffle to 0.5.3 using npm install -g truffle
Last step i did is to update truffle-config.js with the following:
compilers: {
solc: {
version: "0.8.0", // Fetch exact version from solc-bin (default: truffle's version)
// docker: true, // Use "0.5.1" you've installed locally with docker (default: false)
// settings: { // See the solidity docs for advice about optimization and evmVersion
// optimizer: {
// enabled: false,
// runs: 200
// },
// evmVersion: "byzantium"
// }
}
},
that's it then run truffle compile, if it creates a contract folder in react/src and compiled successfully, there will be no error
const path = require("path");
module.exports = {
contracts_build_directory: path.join(__dirname, "client/src/contracts"),
/**
* Networks define how you connect to your ethereum client and let you set the
* defaults web3 uses to send transactions. If you don't specify one truffle
* will spin up a development blockchain for you on port 9545 when you
* run `develop` or `test`. You can ask a truffle command to use a specific
* network from the command line, e.g
*
* $ truffle test --network <network-name>
*/
Related
Works well on connecting to Redis locally and through Official Redis Docker image. But, when I switch to Heroku Redis values for ENV variables. It is unable to connect.
I have tried full url option as well, but that doesn't seem to work for any Redis connections when I need to add options object as 2nd parameter to new Redis(), Url option works if I don't pass any options for only locally and Official Redis Docker image.
Adding only heroku redis URI with no options to new Redis(), looks like it works, but then I get Redis Connection Failure after 10 seconds.
Does Heroku-Redis need some sort of extra preparation step?
import Redis, { RedisOptions } from 'ioredis';
import logger from '../logger';
const REDIS_HOST = process.env.REDIS_HOST || '127.0.0.1';
const REDIS_PORT = Number(process.env.REDIS_PORT) || 6379;
const REDIS_PASSWORD = process.env.REDIS_PASSWORD;
const REDIS_DB = Number(process.env.REDIS_DB) || 0;
const redisConfig: RedisOptions = {
host: REDIS_HOST,
port: Number(REDIS_PORT),
password: REDIS_PASSWORD,
db: Number(REDIS_DB),
retryStrategy: function (times) {
if (times % 4 == 0) {
logger.error('Redis reconnect exhausted after 4 retries');
return null;
}
return 200;
},
};
const redis = new Redis(redisConfig);
redis.on('error', function () {
logger.error('Redis Connection Failure');
});
export default redis;
I'm not sure where you got the idea to use environment variables called REDIS_HOST, REDIS_PORT, REDIS_PASSWORD, and REDIS_DB. Heroku Data for Redis provides a single environment variable that captures all of this:
After Heroku Data for Redis has been created, the new release is created and the application restarts. A REDIS_URL config var is available in the app configuration. It contains the URL you can use to access the newly provisioned Heroku Data for Redis instance.
Here is their example of how to connect from Node.js:
const redis = require("redis");
const client = redis.createClient({
url: process.env.REDIS_URL,
socket: {
tls: true,
rejectUnauthorized: false
}
});
So, change your configuration object accordingly:
const REDIS_URL = process.env.REDIS_URL;
const redisConfig: RedisOptions = {
url: REDIS_URL, // <--
socket: { // <--
tls: true, // <--
rejectUnauthorized: false // <--
}, // <--
retryStrategy: function (times) {
if (times % 4 == 0) {
logger.error('Redis reconnect exhausted after 4 retries');
return null;
}
return 200;
},
};
You are already using an environment variable locally to set your Redis password locally. Replace that with an appropriate REDIS_URL that contains all of your defaults, e.g. something like this:
REDIS_URL=redis://user:password#host:port/database
I installed nightwatch-vrt locally in my project. Npm showed me multiple vulnerities which I ignored.
I created a nightwatch.vrt.conf.js with the following content:
const path = require('path');
const baseConfig = require('./nightwatch.conf.js');
const config = {
...baseConfig,
custom_commands_path: ['node_modules/nightwatch-vrt/commands'],
custom_assertions_path: ['node_modules/nightwatch-vrt/assertions']
};
function generateScreenshotFilePath(nightwatchClient, basePath, fileName) {
const moduleName = nightwatchClient.currentTest.module,
testName = nightwatchClient.currentTest.name;
return path.join(process.cwd(), basePath, moduleName, testName, fileName);
};
config.test_settings.default.globals = {
"visual_regression_settings": {
"generate_screenshot_path": generateScreenshotFilePath,
"latest_screenshots_path": "vrt/latest",
"latest_suffix": "",
"baseline_screenshots_path": "vrt/baseline",
"baseline_suffix": "",
"diff_screenshots_path": "vrt/diff",
"diff_suffix": "",
"threshold": 0.5,
"prompt": false,
"always_save_diff_screenshot": true
}
}
module.exports = config;
My test (simple, just to see if it works) looks like:
module.exports = {
tags: ['x'],
'visual testing':function(browser) {
browser
.url('https://www.kraeuter-und-duftpflanzen.de')
.maximizeWindow()
.assert.visible('.header-main')
.pause(1000)
.assert.screenshotIdenticalToBaseline('.header-main')
//.saveScreenshot('./tests_output/image.png')
.end();
}
}
Now the test passes, no assertions failed, a folder is created and the file is correctly named placed there, but I can only see an field with checkerboard pattern (like the transparent background in vector graphics) in the size of the captured element.
Before the test report messages like this are shown:
[32644:26476:0414/082519.134:ERROR:device_event_log_impl.cc(214)] [08:25:19.134]
USB: usb_device_handle_win.cc:1049 Failed to read descriptor from node connection:
Ein an das System angeschlossenes Gerõt funktioniert nicht. (0x1F)
If I let Nightwatch take a screenshot itself, it is displayed correctly.
Does anyone know, where's the mistake?
it seems that this package is broken and not updated for a very very long time. I advise you to update to this one https://www.npmjs.com/package/#bbc/nightwatch-vrt
Currently getting the following error with MongoDB:
no saslprep library specified. Passwords will not be sanitized
We are using Webpack so simply installing the module doesn't work (Webpack just ignores it). I found this thread which talks about how to exclude it from Webpack compilations, but then I have to manually load it into every Lambda function which led me to Lambda Layers.
Following the Serverless guide on using Lambda layers allowed me to get my layer published to AWS and included in all of my functions, but for some reason, it doesn't install the modules. If I download the layer using the AWS GUI, I get a folder with just the package.json and package-lock.json files.
My file structure is:
my-project
|_ layers
|_ saslprep
|_ package.json
and my serverless.yml is:
layers:
saslprep:
path: layers/saslprep
compatibleRuntimes:
- nodejs14.x
This is not my preferred solution as I'd like to use 256, but the way I got around this error/warning was by changing the authMechanism from SCRAM-SHA-256 to SCRAM-SHA-1 in the connection string. The serverless-bundle most likely needs to add this dependency into their package to enable support for Mongo 4.0 SHA256 (my best guess!).
You can specify this authentication mechanism by setting the authMechanism parameter to the value SCRAM-SHA-1 in the connection string as shown in the following sample code.
const { MongoClient } = require("mongodb");
// Replace the following with values for your environment.
const username = encodeURIComponent("<username>");
const password = encodeURIComponent("<password>");
const clusterUrl = "<MongoDB cluster url>";
const authMechanism = "SCRAM-SHA-1";
// Replace the following with your MongoDB deployment's connection string.
const uri =
`mongodb+srv://${username}:${password}#${clusterUrl}/?authMechanism=${authMechanism}`;
// Create a new MongoClient
const client = new MongoClient(uri);
// Function to connect to the server
async function run() {
try {
// Connect the client to the server
await client.connect();
// Establish and verify connection
await client.db("admin").command({ ping: 1 });
console.log("Connected successfully to server");
} finally {
// Ensures that the client will close when you finish/error
await client.close();
}
}
run().catch(console.dir);
I have set up node:
nearup run localnet --binary-path ~/code/nearcore/target/release
I am trying to run a jest test case:
beforeAll(async function () {
// NOTE: nearlib and nearConfig are made available by near-cli/test_environment
const near = await nearlib.connect(nearConfig)
})
However there is obvious step missing how to create test accounts on your local node. This is the error:
● Test suite failed to run
Can not sign transactions for account test.near, no matching key pair found in Signer.
at node_modules/near-api-js/lib/account.js:83:23
at Object.exponentialBackoff [as default] (node_modules/near-api-js/lib/utils/exponential-backoff.js:7:24)
at Account.signAndSendTransaction (node_modules/near-api-js/lib/account.js:80:24)
at Account.createAndDeployContract (node_modules/near-api-js/lib/account.js:176:9)
at LocalTestEnvironment.setup (node_modules/near-cli/test_environment.js:39:9)
Also looks like near-js-api is hardcoded to deploy only one contract. I need to test multiple contracts. How can I deploy multiple contracts? From near-js-api test_environment.js
class LocalTestEnvironment extends NodeEnvironment {
constructor(config) {
super(config);
}
async setup() {
this.global.nearlib = require('near-api-js');
this.global.nearAPI = require('near-api-js');
this.global.window = {};
let config = require('./get-config')();
this.global.testSettings = this.global.nearConfig = config;
const now = Date.now();
// create random number with at least 7 digits
const randomNumber = Math.floor(Math.random() * (9999999 - 1000000) + 1000000);
config = Object.assign(config, {
contractName: 'test-account-' + now + '-' + randomNumber,
accountId: 'test-account-' + now + '-' + randomNumber
});
const keyStore = new nearAPI.keyStores.UnencryptedFileSystemKeyStore(PROJECT_KEY_DIR);
config.deps = Object.assign(config.deps || {}, {
storage: this.createFakeStorage(),
keyStore,
});
const near = await nearAPI.connect(config);
const masterAccount = await near.account(testAccountName);
const randomKey = await nearAPI.KeyPair.fromRandom('ed25519');
const data = [...fs.readFileSync('./out/main.wasm')];
await config.deps.keyStore.setKey(config.networkId, config.contractName, randomKey);
await masterAccount.createAndDeployContract(config.contractName, randomKey.getPublicKey(), data, INITIAL_BALANCE);
await super.setup();
}
near-js-sdk itself is deploying against mysterious shared-test
case 'ci':
return {
networkId: 'shared-test',
nodeUrl: 'https://rpc.ci-testnet.near.org',
masterAccount: 'test.near',
};
How can I deploy multiple contracts?
You can use masterAccount.createAndDeployContract same as test_environment.js. There is nothing special there except some common init - you can instead create whatever accounts / contracts are needed for your tests directly.
near-js-sdk itself is deploying against mysterious shared-test
This is shared network which can be used to run integration tests. Unless you want to keep your dev work private – it is recommended way to run tests (as hits most realistic environment currently available for testing).
However there is obvious step missing how to create test accounts on your local node.
If you created project using create-near-app you likely have corresponding test.near keys in neardev/ project folder already. That's why above mysterious environment generally works out of box.
For your local environment you need to create test.near yourself:
NODE_ENV=local near create-account test.near --masterAccount some-existing-account
After that you can copy keys to local format (or just reconfigure UnencryptedFileSystemKeyStore to use ~/.near-credentials path):
cp ~/.near-credentials/local/test.near.json project/dir/neardev/local/test.near.json
I have a simple smart contract deployed on the local truffle env using migrate. I am using react-components package to work with the smart contract.
So my issue is that simple getters and setters are working, but when I try to run a method with 2-3 arguments I am getting this exception.
My truffleconfig is as follows:
module.exports = {
// See <http://truffleframework.com/docs/advanced/configuration>
// to customize your Truffle configuration!
contracts_build_directory: path.join(__dirname, "app/src/contracts"),
networks: {
develop: { // default with truffle unbox is 7545, but we can use develop to test changes, ex. truffle migrate --network develop
host: "127.0.0.1",
port: 8545,
network_id: "*",
gas: 6921975,
gasPrice: 25000000000
}
},
solc: {
optimizer: {
enabled: true,
runs: 200
}
}
};
And in my react component I am calling like this:
<div className="section">
<h2>Testing Poni</h2>
<p>
This is a initial test to create Poni
</p>
<p>
<strong>Stored Value: </strong>
<ContractData
drizzle={drizzle}
drizzleState={drizzleState}
contract="PoniOwnership"
method="getMyPonies"
/>
</p>
<ContractForm drizzle={drizzle} contract="PoniOwnership" method="createPoni" />
</div>
My solidity functions are like this:
function createPoni(string memory _code, string memory _imgLink) public onlyOwner poniIsUnique(_code){
uint randDna = _generateRandomDna(_code);
//!!pass imgHash here also later
_createPoni(_code, _imgLink, randDna);
}
function _createPoni(string memory _code, string memory _imgLink, uint _dna) private {
uint id = ponies.push(Poni(msg.sender, _code, _imgLink, _dna, 0, true)) - 1;
poniToOwner[id] = msg.sender;
codeToId[_code] = id;
ownerPoniCount[msg.sender] = ownerPoniCount[msg.sender].add(1);
emit NewPoni(id, _code, _imgLink, _dna);
}
struct Poni {
address owner;
string code;
string imgLink;
uint dna;
}
I have tried to additionally send gas from the drizzle react-component as options are given here: https://www.trufflesuite.com/docs/drizzle/react/react-components, but it throws errors saying function is not payable. I am not able to figure out how to deal with this exception.
You want to set a higher gas for the transaction
You want to tweak the sendArgs({gas:}) on the ContractForm component.
https://www.trufflesuite.com/docs/drizzle/react/react-components#contractform