Deploying Smart Contract On Infura (Kovan Testnet) Using Web3 & Truffle HDWalletProvider - ethereum

For better or worse, I'm following a tutorial from late 2018 to help me understand how to deploy a smart contract on Kovan testnet. I'm aware versioning might be an issue, so before I show the deploy.js here is my package.json:
"dependencies": {
"ganache-cli": "^6.10.2",
"mocha": "^4.1.0",
"solc": "^0.4.25",
"truffle-hdwallet-provider": "0.0.3",
"web3": "^1.0.0-beta.26"
},
My .env:
WALLET_SEED="some 12 word seed phrase"
INFURA_ENDPOINT="https://kovan.infura.io/v3/PROJECT_ID"
The deploy.js:
const dotenv = require("dotenv").config();
const HDWalletProvider = require('truffle-hdwallet-provider');
const Web3 = require('web3');
const { interface, bytecode } = require('./compile');
const provider = new HDWalletProvider(
process.env.WALLET_SEED,
process.env.INFURA_ENDPOINT
);
const web3 = new Web3(provider);
const deploy = async () => {
const accounts = await web3.eth.getAccounts();
console.log('Attempting to deploy from account', accounts[0]);
const result = await new web3.eth.Contract(JSON.parse(interface))
.deploy({ data: bytecode, arguments: ['Hi there!']})
.send({ gas: '1000000', from: accounts[0] });
console.log('Contract deployed to: ', result.options.address);
}
deploy();
The compile works correctly, but when I deploy I get the following error:
UnhandledPromiseRejectionWarning: Error: Insufficient funds. The account you tried to send transaction from does not have enough funds. Required 10000000000000000 and got: 0.
at /Users/richardjarram/code/catonmat/udemy-solidity/solidity_sandbox/node_modules/web3-provider-engine/subproviders/web3.js:15:44
at XMLHttpRequest.request.onreadystatechange (/Users/richardjarram/code/catonmat/udemy-solidity/solidity_sandbox/node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/httpprovider.js:118:13)
I definitely have 1 ETH in my Kovan wallet. The interesting thing is this: When I query my wallet in the following code I get the following output:
const balance = await web3.eth.getBalance('0x...............actualaccount');
console.log(balance)
// => 1000000000000 etc.
But when i query the accounts variable generated by the Web3 provider from my mnemonic phrase I get a completely different account:
const provider = new HDWalletProvider(
process.env.WALLET_SEED,
process.env.INFURA_ENDPOINT
);
const web3 = new Web3(provider);
const accounts = await web3.eth.getAccounts();
console.log(accounts)
// [ '0x..............XYZ']
When I check the funds in the account that web3 constructs for me, I confirm that the balance is indeed 0:
const balance = await web3.eth.getBalance('0x...............XYZ');
console.log(balance)
// => 0
But when I hard-code my actual wallet address into the deploy script as such, it tells me the account does not exist!
const result = await new web3.eth.Contract(JSON.parse(interface))
.deploy({ data: bytecode, arguments: ['Hi there!']})
.send({ gas: '1000000', from: '0x.................actualaccount' });
(node:93528) UnhandledPromiseRejectionWarning: Error: Unknown address - unable to sign transaction for this address: "0x.....................actualaddress"
at /Users/richardjarram/code/catonmat/udemy-solidity/solidity_sandbox/node_modules/web3-provider-engine/subproviders/hooked-wallet.js:185:35
at /Users/richardjarram/code/catonmat/udemy-solidity/solidity_sandbox/node_modules/web3-provider-engine/subproviders/hooked-wallet.js:207:5

In your truffle-config.js where you define the networks to use add 'from: '0x...', ensuring that the contract deploys from the account that you know has the balance.

Related

Sample APIConsumer contract not receiving ChainlinkFulfilled event in Hardhat

I deployed the APIConsumer sample contract (https://docs.chain.link/docs/make-a-http-get-request/) from Remix on Kovan, funded it with LINK, and sent a requestVolumeData transaction from Remix. As can be seen on Etherscan, the ChainlinkFulfilled event was fired: https://kovan.etherscan.io/address/0xde79d39db6b5210f83acf57346d74e5c762ab895#events.
Then I attached to the very same contract in Hardhat using a Kovan fork (with the Alchemy API key), and it never receives the event. Here is my test script:
const { ethers } = require("hardhat");
describe("API", function() {
it("Should make request and get result", async function() {
const ERC20 = await ethers.getContractFactory("ERC20")
const link = await ERC20.attach("0xa36085F69e2889c224210F603D836748e7dC0088"); //Kovan
console.log("name=" + await link.name());
const APIConsumer = await ethers.getContractFactory("APIConsumer");
const apiConsumer = APIConsumer.attach("0xde79d39db6B5210F83acf57346d74E5C762AB895");
//Ensure contract has sufficient LINK
console.log("balanceOf=" + await link.balanceOf(apiConsumer.address));
//Make request
const transaction = await apiConsumer.requestVolumeData()
const tx_receipt = await transaction.wait()
const requestId = tx_receipt.events[0].topics[1]
console.log("requestId=%s", requestId)
//Optionally subscribe to events
// apiConsumer.on("ChainlinkFulfilled", id => {
// console.log("ChainlinkFulfilled: %s", id);
// })
//Wait 30 secs for oracle to callback
await new Promise(resolve => setTimeout(resolve, 30000))
//Now check the result
const result = await apiConsumer.volume()
console.log("API Consumer Volume: %s", result)
});
});
In hardhat.config.js, blockNumber is chosen to be just before the first ChainlinkRequested event, and we can see from the script output that the contract is funded with sufficient LINK.
require("#nomiclabs/hardhat-waffle");
/**
* #type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
solidity: "0.8.7",
networks: {
hardhat: {
forking: {
url: "https://eth-kovan.alchemyapi.io/v2/<API Key>",
blockNumber: 31301193
}
}
},
};
Script output
API
name=ChainLink Token
balanceOf=1000000000000000000
requestId=0x352988e0ddfe5c4349711ed9787069b1ea55bae562f676a08f6103435a874514
API Consumer Volume: 0
Why doesn't ChainlinkFulfilled seem to get fired from the Hardhat test?
Welcome, Peter! There is no oracle listening on your forked network. To test oracles locally you should consider mocking the oracle (hardhat way).

ethers.js call to contract transaction fails

Newbie to ethereum development...
I am using the sample code to keep it as simple as possible.
Using ethers.js and HardHat running on my local network.
The read function works ie. const data = await contract.greet()
The writes do not.
This code does not work, it just silently fails:
async function setGreeting() {
if (!greeting) return
if (typeof window.ethereum !== 'undefined') {
try {
await requestAccount()
const provider = new ethers.providers.Web3Provider(window.ethereum)
const signer = provider.getSigner()
const contract = new ethers.Contract(
greeterAddress,
Greeter.abi,
signer,
)
console.log('contract address = ' + contract.address) // this displays correctly
const transaction = await contract.setGreeting(greeting)
console.log('transaction = ' + transaction) // never displays
await transaction.wait()
} catch (err) {
console.log(err)
}
}
}
No error is thrown.
This line seems to be causing the issue:
const transaction = await contract.setGreeting(greeting)
All I see when testing is what seems to be an exception but nothing logged.
No transaction displays in HardHat.
What am I missing? Should an exception not be thrown?
Thanks!

Firebase Emulator Suite - simple pubsub example

I have read MANY docs/blogs/SO articles on using the Firebase Emulator Suite trying a simple pubsub setup, but can't seem to get the Emulator to receive messages.
I have 2 functions in my functions/index.js:
const functions = require('firebase-functions');
const PROJECT_ID = 'my-example-pubsub-project';
const TOPIC_NAME = 'MY_TEST_TOPIC';
// receive messages to topic
export default functions.pubsub
.topic(TOPIC_NAME)
.onPublish((message, context) => {
console.log(`got new message!!! ${JSON.stringify(message, null, 2)}`);
return true;
});
// publish message to topic
export default functions.https.onRequest(async (req, res) => {
const { v1 } = require('#google-cloud/pubsub');
const publisherClient = new v1.PublisherClient({
projectId: process.env.GCLOUD_PROJECT,
});
const formattedTopic = publisherClient.projectTopicPath(PROJECT_ID, TOPIC_NAME);
const data = JSON.stringify({ hello: 'world!' });
// Publishes the message as JSON object
const dataBuffer = Buffer.from(data);
const messagesElement = {
data: dataBuffer,
};
const messages = [messagesElement];
// Build the request
const request = {
topic: formattedTopic,
messages: messages,
};
return publisherClient
.publish(request)
.then(([responses]) => {
console.log(`published(${responses.messageIds}) `);
res.send(200);
})
.catch((ex) => {
console.error(`ERROR: ${ex.message}`);
res.send(555);
throw ex; // be sure to fail the function
});
});
When I run firebase emulators:start --only functions,firestore,pubsub and then run the HTTP method with wget -Sv -Ooutput.txt --method=GET http://localhost:5001/my-example-pubsub-project/us-central1/httpTestPublish, the HTTP function runs and I see its console output, but I can't seem to ever get the .onPublish() to run.
I notice that if I mess around with the values for v1.PublisherClient({projectId: PROJECT_ID}), then I will get a message showing up in the GCP cloud instance of the Subscription...but that's exactly what I don't want happening :)

SyntaxError: Unexpected token u in JSON at position 0 - node deploy.js

My code keeps returning SyntaxError: Unexpected token u in JSON at position 0.
It deploys from accounts[0] but it does not return a "deployed to" address.
I've tried stringify as well.
I'm new to JS and I'm taking first steps in building my own project.
I had the same problem at my compile.js file but solved it with JSON.parse(solc.compile(JSON.stringify(input). It doesn't seem to work here.
Can someone help?
Here's my deploy.js:
const HDWalletProvider = require("#truffle/hdwallet-provider");
const Web3 = require("web3");
const { interface, bytecode } = require("./compile");
const compiledPurchase = require("./build/Purchase.json");
const provider = new HDWalletProvider(
"12 words",
"testnet"
);
const web3 = new Web3(provider);
const deploy = async() => {
const accounts = await web3.eth.getAccounts();
console.log("Attempting to deploy from account", accounts[0]);
// #####Deploy script#####
const result = await new web3.eth.Contract(
JSON.parse(compiledPurchase.interface)
)
.deploy({ data: compiledPurchase.bytecode })
.send({ gas: "1000000", from: accounts[0] });
console.log("Contract deployed to", result.options.address);
};
deploy();
Confirm that the path you are giving is correct and complete in this line:
const compiledPurchase = require("./build/Purchase.json");
Path to the folder could be different. That depends on your Project directory structure. But when you compile with truffle, it generates a json file in build/contracts folder.
Then change your deployment script like this:
const contract = new web3.eth.Contract(compiledPurchase.abi)
contract.deploy({ data: compiledPurchase.bytecode })
.send({ gas: "1000000", from: accounts[0] })
.then(function(result){
console.log("Contract deployed to", result.options.address)
});

Error when subscribing to ERC-20 (BAT, i.e. Basic Attention Token)

I'm trying to subscribe to BAT(Basic Attention Token) ERC-20 token "Transfer" event to detect any transaction made to my ethereum address using web3 in nodejs. I'm using parity (Parity/v1.10.6-stable-bc0d134-20180605/x86_64-linux-gnu/rustc1.26.1) node running on same local machine -
parity --jsonrpc-hosts all --jsonrpc-apis all --ws-apis all --ws-hosts all --ws-origins all --ws-interface all
Here is the code that I've used to subscribe -
const Web3 = require('web3');
const abi = require('human-standard-token-abi');
var contract = '0x0D8775F648430679A709E98d2b0Cb6250d2887EF'; //BAT contract address
var web3Socket = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546'));
function tokenEventListener = (address) => {
let token = new web3Socket.eth.Contract(abi, address);
console.log(address);
let subscription = token.events.Transfer({
fromBlock: 0
})
.on('data', (event) => {
// do something
})
.on('error', console.error);
}
tokenEventListener(contract);
I get an error when I run the code -
Error: CONNECTION ERROR: Couldn't connect to node on WS
It means that your node is not set up properly. Change:
var web3Socket = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546'));
to
var web3Socket = new Web3(new Web3.providers.WebsocketProvider('wss://mainnet.infura.io/ws'));
This will connect to the Infura node which doesn't require you to host one.