Could not interact with contract in BSC mainnet but succeed in testnet (but still a standard transfer) - smartcontracts

I may send raw transaction by sendSignedTransaction to contract address on BSC testnet, and it succeed but this is just a standard transaction; it's not contract call like I want.
But on BSC mainnet, it always failed with error: Warning! Error encountered during contract execution [execution reverted]
Please help me check code below then tell me where issue, any comment, reply or guess welcome; many thanks.
For testnet, it always succeed but it was a a standard transaction, link to image. While I wanna interact with contract, result should show field Interacted With (To)
var minABI = [
{
"constant": true,
"inputs": [
{
"name": "_claimer",
"type": "uint256"
},
{
"name": "_amount",
"type": "uint256"
},
{
"name": "_sig",
"type": "bytes"
}
],
"name": "claim",
"outputs": [],
"payable": true,
"stateMutability": "payable",
"type": "function"
}
];
var web3 = new Web3('https://data-seed-prebsc-1-s1.binance.org:8545'); // testnet
//var web3 = new Web3('https://bsc-dataseed.binance.org:443'); // mainnet
var _from = '0x2151...';
var _to = '0x7f617...';
var _sign = '0x5eddd...';
var PRIVATE_KEY = 'da65f...';
var contract = new web3.eth.Contract(minABI, _to, {from: _from});
var _nonce = await web3.eth.getTransactionCount(_from, 'latest');
var _signEncoded = contract.methods.claim(_nonce, '17390000000000000000', _sign).encodeABI();
var esGas = await web3.eth.estimateGas({
"from" : _from,
"nonce" : _nonce,
"to" : _to,
"data" : _signEncoded
});
var sentValue = gasPrice * esGas;
var transaction = {
'to': _to,
'value': sentValue,
'gas': esGas,
'nonce': _nonce,
'data': _signEncoded,
};
var signedTx = await web3.eth.accounts.signTransaction(transaction, PRIVATE_KEY);
var tx = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
For mainet, if I used _signEncoded in web3.eth.estimateGas it returns error: execution reverted: Invalid signature, I must use _sign to send transaction but it still always failed with error Warning! Error encountered during contract execution [execution reverted] link to image
var esGas = await web3.eth.estimateGas({
"from" : _from,
"nonce" : _nonce,
"to" : _to,
"data" : _sign
});

Contract deployed on mainnet
But the JS snippet is trying to call the contract on testnet (where it's not deployed).
var web3 = new Web3('https://data-seed-prebsc-1-s1.binance.org:8545'); // testnet
//var web3 = new Web3('https://bsc-dataseed.binance.org:443'); // mainnet
So you need to either deploy it on testnet as well, or use a mainnet (where it's already deployed) web3 provider.
if I want to call this claim, I must call via its contract: contract.methods.claim(_nonce, 'amount', _sign).call() ? sendSignedTransaction is just a normal transfer and could not be used in my case?
The contract.methods.claim(...).call() is an shorthad for calling the function. sendSignedTransaction() can be used to send a transaction - by default without invoking any function, but you can also define its data param to execute the claim() function.
Mind that there's a difference between a call (read-only; performed by the functionName().call() in web3) and a transaction (read-write; performed by the functionName().send() function in web3). Based on the context of your question, I'm guessing you want to send a transaction (executing the claim() function) - not perform a call (to the claim() function).

Related

How to get the ressources address of a badge

I'm trying to build an Auction web application based on a scrypto smartcontract.
I have a register function that return a badge, from which I can build proof to call other methods that need authentication.
To build the proof, I need the address of the badge; using the pte-sdk, how would that be possible ?
I use :
const manifestRegistration = new ManifestBuilder()
//call the register function
.callMethod(auction.auctionId, "register", [])
//deposit the resource into my account
.callMethodWithAllResources(accountAddress, "deposit_batch")
.build()
.toString()
const receiptRegistration = await signTransaction(manifestRegistration);
console.log(receiptRegistrationt)
here is receipt :
{
"transactionHash": "b737899a3b78692d2ba49d83ccedeacd66f6168d107a2962828d621d6c73cb37",
"status": "Success",
"outputs": [
"{\"type\":\"Bucket\",\"value\":\"Bucket(1027u32)\"}",
"{\"type\":\"Unit\"}"
],
"logs": [],
"newPackages": [],
"newComponents": [],
"newResources": []
}
How do I know what is the resource in the returned bucket ?
Thank you
The first thing that pops into my head of solving this is returning the address as a string
pub fn register() -> (Bucket, String) -> {
...
(badge, badge.resource_address().to_string())
}
This should pop up in the outputs array

Not getting event from smart contract on ethers.js

I have contract this part is simply creating smart contract for NFT. At the end of the createToken() I am emitting event.
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.3;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
contract NFT is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
address contractAddress;
event ItemCreated(
uint256 indexed tokenId
);
constructor(address marketplaceAddress) ERC721("Metaverse Tokens", "METT") {
contractAddress = marketplaceAddress;
}
function createToken(string memory tokenURI) public returns (uint) {
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(msg.sender, newItemId);
_setTokenURI(newItemId, tokenURI);
setApprovalForAll(contractAddress, true);
emit ItemCreated(newItemId);
}
}
I am trying to read event ItemCreated on ethers.js
const web3Model = new Web3Modal()
const connection = await web3Model.connect()
const provider = new ethers.providers.Web3Provider(connection)
const signer = provider.getSigner()
let contract = new ethers.Contract(nftaddress, NFT.abi, signer)
let transaction = await contract.createToken(url)
let tx = await transaction.wait()
console.log('tx' ,tx)
let event = tx.events[0]
console.log('event', event)
Unfortunately, the response is not giving me any event
Please see below response. evens property is empty
{
"to": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
"from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"contractAddress": null,
"transactionIndex": 0,
"gasUsed": {
"type": "BigNumber",
"hex": "0x5858"
},
"logsBloom": "0x0000000000000...",
"blockHash": "0xe66248c22832b34776c6720a6bec19bf20e9ba9af4a63ff25bd0f0689f19f037",
"transactionHash": "0xc6de2da6186ca972cc69efa265c7da5e6d780a0c25d4ad849aa4be4be9cac501",
"logs": [],
"blockNumber": 1,
"confirmations": 1,
"cumulativeGasUsed": {
"type": "BigNumber",
"hex": "0x5858"
},
"effectiveGasPrice": {
"type": "BigNumber",
"hex": "0x8d8f9fc0"
},
"status": 1,
"type": 2,
"byzantium": true,
"events": []
}
events are empty
I am sure event is emitted as I checked in hardhat-tracker
npx hardhat test --logs
NFT market
[Receiver] Transfer(from=0x0000000000000000000000000000000000000000, to=[Sender], tokenId=1)
[Receiver] ApprovalForAll(owner=[Sender], operator=0x5FbDB2315678afecb367f032d93F642f64180aa3, approved=true)
[Receiver] ItemCreated(tokenId=1)
[Receiver] Transfer(from=0x0000000000000000000000000000000000000000, to=[Sender], tokenId=2)
[Receiver] ApprovalForAll(owner=[Sender], operator=0x5FbDB2315678afecb367f032d93F642f64180aa3, approved=true)
[Receiver] ItemCreated(tokenId=2)
Any idea what I am dong wrong?
Below link to the repo https://github.com/Filip-Konkowski/Polygon-nft-market
Are you sure you have selected the correct network in your metamask? The same thing happened to me once :D Also, be sure to deploy using the network parameter such as npx hardhat run scripts/deploy.js --network localhost

Web3.js 1.2 invocation smart contract method and can not return correct result

When I invoke the smart contract deployed, I don't get the correct result!
I have googled, but can not fine any help.
Here is my contract:
pragma solidity >=0.4.22 <0.6.0;
contract LYQFirst{
function userRegister() public payable returns(string memory)
{
return "Hello World";
}
}
and my web3.js version is 1.2 and the web3.js code is as follows:
var Web3 = require('web3');
if (typeof web3 !== 'undefined') {
console.log("Hello World");
web3 = new Web3(web3.currentProvider);
} else {
// set the provider you want from Web3.providers
web3 = new Web3(new Web3.providers.HttpProvider ("http://localhost:8545"));
}
var contract1 = new web3.eth.Contract([
{
"constant": false,
"inputs": [],
"name": "userRegister",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": true,
"stateMutability": "payable",
"type": "function"
}
],"0xd62f32665ac53749ded4a38d984d70f180d2908a");
contract1.methods.userRegister().send
({from: "0x18244fbf3b47175cd6b4a1183a476c9e70cb7368",gas:200000}).then (function(error,result){
console.log(error);
console.log("result="+result);
});
The geth including followings modules and their versions.
modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0.
I installed web3.js 1.2 by npm install web3 for interacting with geth.
The result I got from web3 code is as following:
{ blockHash:
'0x4865c3845d88d7022962833b663ed298f1a0e5b2e7e4905c7b0c968972790174',
blockNumber: 3186,
contractAddress: null,
cumulativeGasUsed: 21847,
from: '0x18244fbf3b47175cd6b4a1183a476c9e70cb7368',
gasUsed: 21847,
logsBloom:
'0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
root:
'0x0141214730cebc516bf7036c8b36a24af0a29dbc11ef8ef9daf05448bb84eec5',
to: '0xd62f32665ac53749ded4a38d984d70f180d2908a',
transactionHash:
'0x804d4751eb7ab6b5f31f709dafc98bfa0b7433758ac9b0d58348b34173f832b8',
transactionIndex: 0,
events: {} }
result=undefined
<<< Process finished (PID=9824). (Exit code 0)
You cannot get return value if it's a transaction (send, not call) from Javascript. Transactions return transaction receipt, and that's what you got.
If you need the value, store it an a public storage variable and call it's getter function.

Internationalization ( i18n ) for express-validator

Is it possible to get messages returned by express-validator into a language other than english for internationalization (i18n) ?
I tried looking into the source code and I could not find it.
express-validator
Thanks
It's probably something you have to create yourself, but it shouldn't be too hard.
When you assign an error message with withMessage() you can send more than just a single string. You can for example send an object. So you can put the error messages, for all the languages, for a particular error, in an object.
Here is an example:
Route:
const countValidation = require('./count.validation');
router
.route('/blogposts')
.get(
countValidation.count,
blogpostController.blogpostsGetAll,
);
Validator (in a separate file called count.validation.js):
const message = {
english: 'count must be between 1 and 1000',
chinese: 'count must be between 1 and 1000, but in chinese',
};
module.exports.count = [
check('count')
.optional()
.isInt({ min: 1, max: 1000 })
.withMessage(message)
];
This response will be sent when validation fails:
{
"errors": {
"count": {
"location": "query",
"param": "count",
"value": "-1",
"msg": {
"english": "count must be between 1 and 1000",
"chinese": "count must be between 1 and 1000, but in chinese"
}
}
}
}
In this particular example the front-end has to choose what error message to display depending on user settings or user agent.
It's also possible to deal with what error message to use on the server side, if we know what language the client is using from the request. We could for example read the accept-language header in the request. Here is an example of how that could be done:
The controller function:
Rather than using this (standard handling of errors, almost straight from the readme):
module.exports.blogpostsGetAll = (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.mapped() });
}
// The rest of the function...
};
we use this:
module.exports.blogpostsGetAll = (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
const errorsInProperLanguage = handleLanguages(req.headers, errors.mapped());
return res.status(422).json({ errors: errorsInProperLanguage });
}
// The rest of the function...
};
Example function to only use one language:
function handleLanguages(headers, errorsMapped) {
const language = headers['accept-language'].split(',')[0];
for (let errorKey in errorsMapped) {
errorsMapped[errorKey].msg = errorsMapped[errorKey].msg[language];
}
return errorsMapped;
}
Because the accept-language header contains language codes, not language names, we have to modify the message object slightly:
const message = {
'en-US': 'count must be between 1 and 1000',
'zh-CH': 'count must be between 1 and 1000, but in chinese',
};
The message object HAS to contain the first language code in the accept-language header for this to work. The handleLanguage function doesn't handle errors. It's only an example to show how it could be done; don't use it directly.
The error message would change to
{
"errors": {
"count": {
"location": "query",
"param": "count",
"value": "-1",
"msg": "count must be between 1 and 1000, but in chinese"
}
}
}
when the first language in accept-language is zh-CH.
This is now possible with express-validator v5.0.0.
If you pass withMessage() a function, it will be called with the field value, the request, its location and its path.
Example from the docs:
check('something').isInt().withMessage((value, { req, location, path }) => {
return req.translate('validation.message.path', { value, location, path });
}),

Google Script button_action fetching error

I am trying to use Sniply API with the following Google Script code, yet i keep receiving an error message. Except the button configuration everything seems to work properly, btw.
The code looks like:
// Main Parmaters
var url = "picky.com"
var message = "This is a text from the Google Spreadsheet API2"
// Button Parameters (Optional)
var button_text = "I am a button2"
var button_url = "mailto:info#picky.com"
var button_background_color = "#000000"
var button_text_color = "#ffffff"
// Button (Optional)
var button_action =
{
"text": button_text,
"url": button_url,
"text_color": button_text_color,
"background_color": button_background_color,
}
var sniply =
{
"button_action": button_action,
"url": url,
"message": message,
}
var options =
{
"method": "post",
"headers" : {
"Authorization" : accesstoken,
},
"payload": sniply,
}
var response = UrlFetchApp.fetch('http://snip.ly/api/snips/', options);
Logger.log(response.getContentText());
The error message, I receive is:
Request failed for http://snip.ly/api/snips/ returned code 400. Truncated server response: {"button_action": [{"non_field_errors": ["Invalid data"]}]} (use muteHttpExceptions option to examine full response)
I would be grateful in case you can help me..
Cheers,
EMG
You are configuring the objects with an extra comma on the end. Try removing the comma:
You have:
var button_action =
{
"text": button_text,
"url": button_url,
"text_color": button_text_color,
"background_color": button_background_color,
}
There is an extra comma at the end of:
"background_color": button_background_color,
That's an incorrect syntax. I'm not saying that is the problem, but I'd start there first.