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

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.

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!

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)
});

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

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.

connection in channels.js returns undefined?

I'm trying to establish a real-time socket connection to my client
side via feathers channels. It works without any sort of
authentication. But if i add the following login action scoket is
throwing a weak map key error.
app.on('login', (authResult, { connection }) => {
console.log(connection) // returns undefined
....
})
This is the error I'm receiving
Unhandled Rejection at: Promise Promise { TypeError:
Invalid value used as weak map key
at WeakMap.set ()
app.on('login', (authResult, { connection }) => {
console.log("============>>", connection)
if (authResult && connection) {
app.channel('anonymous').leave(connection);
if (authResult.user && authResult.user['chanelName']) {
let channelName = authResult.user['chanelName'].toString();
channelName = channelName.substr(0, 5)
app.channel(`channel/${channelName}`).join(connection);
} else
app.channel('authenticated').join(connection)
}
});
The connection object is undefined, i think that causes the problem.
Anu suggestions?
Please provide the client side script.
According to fethers documentation connection can be undefined if there is no real-time connection, e.g. when logging in via REST.
You should authenticate your client.
Sample script
const feathers = require('#feathersjs/feathers');
const socketio = require('#feathersjs/socketio-client');
const io = require('socket.io-client');
const auth = require('#feathersjs/authentication-client');
const socket = io('http://localhost:3031');
const app = feathers();
// Setup the transport (Rest, Socket, etc.) here
app.configure(socketio(socket));
const options = {
header: 'Authorization', // the default authorization header for REST
prefix: '', // if set will add a prefix to the header value. for example if prefix was 'JWT' then the header would be 'Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOi...'
path: '/authentication', // the server-side authentication service path
jwtStrategy: 'jwt', // the name of the JWT authentication strategy
entity: 'user', // the entity you are authenticating (ie. a users)
service: 'users', // the service to look up the entity
cookie: 'feathers-jwt', // the name of the cookie to parse the JWT from when cookies are enabled server side
storageKey: 'feathers-jwt', // the key to store the accessToken in localstorage or AsyncStorage on React Native
storage: undefined // Passing a WebStorage-compatible object to enable automatic storage on the client.
}
app.configure(auth(options))
app.authenticate({
strategy: 'jwt',
accessToken: '<JWT TOKEN>'
}).then(() => {
console.log("Auth successfull")
const deviceService = app.service('myService');
deviceService.on('created', message => console.log('Created a message', message));
}).catch(e => {
console.error('Authentication error', e);
// Show login page
});
Hope this will help you.