I need to check if a specific NFT is in a specific wallet, there is an API or a way to do it programmatically?
Thanks a lot.
Assuming the NFT is published onchain and its collection contract implements the ERC-721 standard, you can call the ownerOf() function (defined in the standard) on the collection contract.
Example using web3js:
const collection = new web3.eth.Contract(abiJson, collectionAddress);
const owner = await collection.methods.ownerOf(tokenId).call();
return owner == desiredAddress;
For the ERC-1155 standard, you can use the balanceOf() function.
const balance = await collection.methods.balanceOf(owner, ,tokenId).call();
return balance > 0;
Related
I'm trying to switch my dapp from Web3Provider to WebSocketProvider,
form this:
const provider = new ethers.providers.Web3Provider(window.ethereum)
const accounts = await window.ethereum.request({ method: "eth_accounts" })
const account = accounts[0]
const signer = provider.getSigner()
to this:
const provider = new ethers.providers.WebSocketProvider("ws://localhost:8545") <-
const accounts = await window.ethereum.request({ method: "eth_accounts" })
const account = accounts[0]
const signer = provider.getSigner()
With this change I can interact with the Contract only with account that creates and deploy the smart contract, also, the transactions have no confirmation from the user. However, when I try to call some Contract function with another address I get this error:
On the fourth line, the value of the "from" key is different from the address actually selected in the metamask, in fact it is the address of the creator of the Smart Contract. There seems to be some problem with the signer or what? With Web3Provider everything works fine.
Can you help me in any way or tell me more about WebSocketProvider?
Thanks in advance
I am trying to get the contract ABI using the Etherscan API, and then create a contract instance and call a method. I am able to get the ABI from Etherscan but when creating the contract object I am getting this error: "You must provide the json interface of the contract when instantiating a contract object."
This is what my code looks like
let url = 'https://api.etherscan.io/api?module=contract&action=getabi&address=0x672C1f1C978b8FD1E9AE18e25D0E55176824989c&apikey=<api-key>';
request(url, (err, res, body) => {
if (err) {
console.log(err);
}
let data = JSON.parse(body);
let contract_abi = data.result;
console.log(contract_abi)
let contract_address = '0x672C1f1C978b8FD1E9AE18e25D0E55176824989';
const contract = new web3.eth.Contract(contract_abi);
const contract_instance = contract.at(contract_address);
// Call contract method
})
When I console.log the contract_abi I see the ABI data. I've also tried creating the contract by doing
const contract = new web3.eth.Contract(contract_abi, contract_address)
Thanks!
data.result contains the JSON ABI as a string. You need to decode it as well to an object.
let contract_abi = JSON.parse(data.result);
Also, it's possible that you're using a deprecated version of Web3 that supports the contract.at() syntax.
But if you're using the current version, you'd get the contract.at is not a function error. In that case, you need to pass the address as the second argument of the Contract constructor.
const contract = new web3.eth.Contract(contract_abi, contract_address);
I want to iterate over all token ids of a ethereum ERC-721 contract.
Some contracts have counting ids (0, 1, 2, 3, ...) which is easy, but some have random ids, e.g. https://etherscan.io/token/0xf87e31492faf9a91b02ee0deaad50d51d56d5d4d#inventory
Sadly etherscan only shows the last 10000 token ids used, but I want to iterate over all 79490.
Is there a way to accomplish this? For me, everything is fine. Setup my own ethereum node, using some API.
You can loop through all Transfer() events emitted by the collection contract.
You're looking for transfers from address 0x0 (minted tokens). And excluding from the list transfers to address 0x0 (destroyed tokens).
One way to achieve this is by using the Web3 Contract getPastEvents() function (docs).
const myContract = new web3.eth.Contract(abiJson, contractAddress);
myContract.getPastEvents('Transfer', {
filter: {
_from: '0x0000000000000000000000000000000000000000'
},
fromBlock: 0
}).then((events) => {
for (let event of events) {
console.log(event.returnValues._tokenId);
}
});
There's no easy way to do it with an Ethereum node in a contract-agnostic way...the ERC-721 does not specify any interface methods that allow querying for all token ID, so unless the contract you're looking at uses sequential token ids, there's no way to guess all token ids from a simple node query.
Unless you want to iterate over the whole transaction history of the contract to get the ids of every minted NFT (you'd need an archive node for that, as a full node would not have the full transaction history) you should use an API from services that index all NFT activity.
You could use this API from CovalentHQ:
https://www.covalenthq.com/docs/api/#/0/Class-A/Get-NFT-Token-IDs-for-contract/lng=en
Or this one from Moralis:
https://docs.moralis.io/moralis-server/web3-sdk/token#getalltokenids
I needed the same with Ethers instead of Web3, here i the code snippet for ethers.js:
const getTransferEvents = async () => {
const provider = new ethers.providers.Web3Provider(window.ethereum)
const contract = new ethers.Contract("address", "abi", provider);
const events = await contract.queryFilter('Transfer', 0);
console.log(events);
};
I am using tron web to query transactions of an address but it does not return transactions sent to that address where token transferred is TRC20.
This does not work.
I want to get the transactions on an address and get both TRX, trc10 and trc20 transactions.
What am I doing wrong or how to do that?
Here is my code block:
tronWeb.setDefaultBlock("latest");
var result = await tronGrid.account.getTransactions(address, {
only_confirmed: true,
only_to: true,
limit: 10
});
console.log(JSON.stringify(result));
})();
After a lot of research, I found out one can easily query contract events at intervals to get transactions on that contract address and you can then filter it for the address you are watching since you can't get a webhook or websocket with your trongrid/tronweb implementation.
Here is a sample file I used to achieve this and it works great for monitoring many address even with different contract addresses.
Note: In my own implementation, this node file is called from another file and other logistics are handled in the other file, but below you see how I queried the transfer events emitted by the specified contract
const TronWeb = require("tronweb");
const TronGrid = require("trongrid");
const tronWeb = new TronWeb({
fullHost: "https://api.trongrid.io"
});
const tronGrid = new TronGrid(tronWeb);
const argv = require("minimist")(process.argv.slice(2));
var contractAddress = argv.address;
var min_timestamp = Number(argv.last_timestamp) + 1; //this is stored for the last time i ran the query
(async function() {
tronWeb.setDefaultBlock("latest");
tronWeb.setAddress("ANY TRON ADDRESS"); // maybe being the one making the query not necessarily the addresses for which you need the transactions
var result = await tronGrid.contract.getEvents(contractAddress, {
only_confirmed: true,
event_name: "Transfer",
limit: 100,
min_timestamp: min_timestamp,
order_by: "timestamp,asc"
});
result.data = result.data.map(tx => {
tx.result.to_address = tronWeb.address.fromHex(tx.result.to); // this makes it easy for me to check the address at the other end
return tx;
});
console.log(JSON.stringify(result));
})();
You are free to customize the config data passed to the tronGrid.contract.getEvents method. Depending on how frequently transactions come on the contract you are monitoring you should DYOR to know at what interval is great for you and what limit value you should pass.
Refer to https://developers.tron.network/docs/trongridjs for details.
I found a API that can take TRC20 transactions, but I haven't found an implementation in webtron.
https://api.shasta.trongrid.io/v1/accounts/address/transactions
Related document:
https://developers.tron.network/reference#transaction-information-by-account-address
Presently, I have a smart contract successfully deployed to the Rinkeby testnet, I'm having trouble accessing the method in question using web3 version 1.0.
Here's my web3 code, which instantiates a contract instance and calls a contract method:
const contractInstance = new web3.eth.Contract(abiDefinition, contractAddress);
var value = web3.utils.toWei('1', 'ether')
var sentTransaction = contractInstance.methods.initiateScoreRetrieval().send({value: value, from: fromAddress})
console.log('event sent, now set listeners')
sentTransaction.on('confirmation', function(confirmationNumber, receipt){
console.log('method confirmation', confirmationNumber, receipt)
})
sentTransaction.on('error', console.error);
And here is my smart contract, or rather a version of it stripped down to the relevant bits:
contract myContract {
address private txInitiator;
uint256 private amount;
function initiateScoreRetrieval() public payable returns(bool) {
require(msg.value >= coralFeeInEth);
amount = msg.value;
txInitiator = msg.sender;
return true;
}
}
I am not able to get to the console.log that is setting the event listeners on the web3 side, and I am not getting an error of any kind thrown. I'm certainly not getting the consoles from the actual event listeners. I am guessing something is wrong with the way I'm sending the transaction, but I think I am correctly following the pattern documented below: https://web3js.readthedocs.io/en/1.0/web3-eth-contract.html#methods-mymethod-send
Does anyone have any insight on how to use web3 1.0 to make contract method calls correctly? Am I doing something wrong with how I'm passing options, etc.?
Thanks!
I believe you forgot to specify your HttpProvider for your web3, thus you're not connecting to live Rinkeby network, and by default web3 is running on you local host, which is why even if you provide the right contract address, there's nothing there.
To connect to live network, I would strongly encourage you to use Infura Node by ConsenSys.
const Web3 = require("web3");
const web3 = new Web3(new Web3.providers.HttpProvider("https://rinkeby.infura.io"));
Then by now, everything should work perfectly fine.
First, you need to generate your transaction ABI using encodeABI(), here is an example:
let tx_builder = contractInstance.methods.myMethod(arg1, arg2, ...);
let encoded_tx = tx_builder.encodeABI();
let transactionObject = {
gas: amountOfGas,
data: encoded_tx,
from: from_address,
to: contract_address
};
Then you have to sign the transaction using signTransaction() using private key of sender. Later you can sendSignedTransaction()
web3.eth.accounts.signTransaction(transactionObject, private_key, function (error, signedTx) {
if (error) {
console.log(error);
// handle error
} else {
web3.eth.sendSignedTransaction(signedTx.rawTransaction)
.on('receipt', function (receipt) {
//do something
});
}