How to decode transaction input data using `ethers.utils.defaultAbiCoder` - javascript

I'm fetching transaction data using Etherscan API. This is the example result I'm getting:
{
blockNumber: '7409930',
timeStamp: '1639151980',
hash: '...',
nonce: '4124',
...
input: '0x9d90e4c8000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000093238bb66b5d15b4152c5db574e3397ff1b1a450',
contractAddress: '',
cumulativeGasUsed: '403775',
gasUsed: '1162315',
confirmations: '191308'
}
I now need to figure out the event type (contract method, e.g. TransferOwnership, stakeTokens,...) for this transaction. This data is stored in input property of this object.
I managed to accomplish this using abi-decoder library, but I want to accomplish the same thing using ethers's utility method (whichever).
My current implementation:
const abiDecoder = require("abi-decoder");
abiDecoder.addABI(contractAbi);
// "item" is transaction data, input property is encoded stuff from which I want to get the contract method used by this transaction
const decodedInput = abiDecoder.decodeMethod(item.input);
// contract method
console.log(decodedInput.name);
I was reading through ether's documentation (https://docs.ethers.io/v5/api/utils/abi/coder/), but I can't figure it out.

you can try what is recommended in this: https://github.com/ethers-io/ethers.js/issues/423 . but if you are interacting with BSC, this is not possible due to the error input data too big causing Error in Big Number Number can only safely store up to 53 bits

Related

How can I use DEFAULT values via knex insert?

My goal is to dynamically insert data into a table via knex.
Code looks like this:
const knexService = require("../knexService.js")
async function insertObjectToKnex() {
const insertObject = {
id: "DEFAULT",
someKey: "someValue"
};
await knexService.db("table").insert(inserObject);
}
On DEFAULT the next free id should be used as database id - table is configured and it works with raw sql. With knex.js I get the following error:
invalid input syntax for type integer: "DEFAULT"
Using the useNullAsDefault: true, config is not possible, because the id is not nullable.
How can I trigger the default value in knex - I did not find anything in the documentation or with google, that could at least give a hint to this issue!
While it is not mentioned in the documentation of knex.js one should simply not add fields with a DEFAULT assignement to a query. This will set the default value to the row column.

Setting dataType JSON in aws-sdk for sqs

Im just trying to send a json object to sqs queue by using aws-sdk npm package.
const sqsMessage = {
MessageAttributes: {
"data": {
DataType: "String",
StringValue: payload.data
}
},
MessageBody: JSON.stringify(payload),
QueueUrl: queueUrl
If i pass json object in data attribute it tells it expected String, if i add Json then it also throws an error about type, does anyone know a workaround or what to use to get the json?
Some useful links i've found,
1)https://blog.chrismitchellonline.com/posts/aws-sqs-message-with-attributes/
https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-send-message.html
Would really appreciate some guidance on this
Can you share the error message that you're receiving. And can you show us an example of payload that you're constructing? Basically, the allowable values for dataType are found here: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_MessageAttributeValue.html
Specifically, this part: "Amazon SQS supports the following logical data types: String, Number, and Binary. For the Number data type, you must use StringValue."
So when it comes to constructing the value for your key MessageBody, you want to use JSON. So the type must be string and your value, it has to be valid JSON that's really a string and the inner quotes escaped. So for example, something like this:
"{\"foo\": \"bar\"}"
I ran into this same issue while writing unit tests in goLang and it works. I know this is 11 months later, but hopefully this helps you or someone else in the future :)

How to send javascript object literals from a Node backend to the browser frontend?

I am using Node where I have JavaScript object literals with methods in the backend, e.g.:
const report = {
id: 1,
title: 'Quarterly Report for Department 12345',
abstract: 'This report shows the results of the sales and marketing divisions.',
searchText: function () {
return this.title + '|' + this.abstract;
}
};
And I want to send these object literals to the frontend via AJAX and be able to call the methods on these objects as I can in the backend.
But even though I can send the objects to the frontend without JSON.stringify(), they are still converted to plain JSON by the time they reach my frontend:
Am I missing something, or is there not a way to send full object literals from backend to frontend. I'm using Axios.
But even though I can send the objects to the frontend without JSON.stringify(),
It sounds like you are using JSON.stringify … just indirectly (via a library).
JSON has no function data type. So you can't just use JSON.
You have a few options.
Listed in the order I'd recommend them in.
Resolve the methods
In your example, your function simple return this.title + '|' + this.abstract; so you could replace it with a string:
const report = {
id: 1,
title: 'Quarterly Report for Department 12345',
abstract: 'This report shows the results of the sales and marketing divisions.',
searchText: 'Quarterly Report for Department 12345|This report shows the results of the sales and marketing divisions.'
}
};
You could use the replacer argument of JSON.stringify to do this automatically for any method on the object.
This is the simplest option but results in data that doesn't update dynamically so it might not be suitable for your needs.
Add the methods with client-side code
Send a simple object which doesn't have the method but does have a field which describes the type of object it does.
Then inflate it on the client:
const type = ajaxResponse.type;
const Constructor = collectionOfConstructorFunctions[type];
const data = new Constructor(ajaxResponse.data);
Send JavaScript instead
You could use JSONP instead of Axios.
The response would be application/javascript instead of application/json so you could encode function expressions in the returned data.
I don't recommend this option.
Encode the functions in the JSON and then include them client-side
This is horrible.
const report = {
id: 1,
title: 'Quarterly Report for Department 12345',
abstract: 'This report shows the results of the sales and marketing divisions.',
searchText: "return this.title + '|' + this.abstract;"
}
and then, on the client:
report.searchText = new Function(report.searchText);
console.log(report.searchText());
This is effectively using eval. Don't do it.

In sails/waterline get maximum value of a column in a database agnostic way

While using sails as ORM (version 1.0), I notice that there is a function called Model.avg (as well as sum). - However there is not a maximum or minimum function to get the maximum or minimum from a column in a model; so it seems this is not necessary because it is covered by other functions already?
Now in my database I need to get the "maximum id" in a list; and I have it working for postgresql by using a native query:
const maxnum = await Order.getDatastore().sendNativeQuery('SELECT MAX(\"orderNr\") FROM \"order\"')
While this isn't the most difficult thing, it is not what I truly want: it is limited to only sql-based datastores (so we wouldn't be able to move easily to mongodb); and the syntax might actually be even different for another sql database type.
So I wonder - can this be transformed in such a way it doesn't rely on sendNativeQuery?
You can try .query() to execute a raw SQL query using the specified model's datastore and if u want u can try pg , an NPM package used for communicating with PostgreSQL databases:
Pet.query('SELECT pet.name FROM pet WHERE pet.name = $1', [ 'dog' ]
,function(err, rawResult) {
if (err) { return res.serverError(err); }
sails.log(rawResult);
// (result format depends on the SQL query that was passed in, and
the adapter you're using)
// Then parse the raw result and do whatever you like with it.
return res.ok();
});
You can use the limit and order options waterline provides to get a single Model with a maximal value (then just extract that value).
const orderModel = await Order.find({
where: {},
select: ['orderNr'],
limit: 1,
sort: 'orderNr DESC'
});
console.log(orderModel.orderNr);
Like most things in Waterline, it's probably not as efficient as an SQL SELECT MAX query (or some equivalent in mongo, etc), but it should allow swapping out the database with no maintenance. Last note, don't forget to handle the case of no models found.

SAPUI5 Create OData entity with dates - generates incorrect request payload that ends in CX_SXML_PARSE_ERROR

We are trying to create an entity that has date attributes via an odata service. Backend is an sap system. This entity has only 3 key attributes plus a bunch of other attributes. We have identified that dates in the keys are the root cause of the problem.
Keys:
Pernr type string,
begda type datetime
endda type datetime.
The code below, (which does not work), has been severely simplified when trying to troubleshoot the issue. At the moment, it reads an entity from an entity set and immediately tries to create one with exactly the same data.
Code:
var oODataModel = new sap.ui.model.odata.ODataModel("/sap/opu/odata/sap/Z_PERSONAL_DATA_SRV/");
//Test entity to be saved
var entity = null;
//Handler for read error
var handleReadE = function (oEvent){
alert("error");
};
//Handler for read success
var handleRead = function (oEvent){
//Get the data read from backend
entity = oEvent.results[0];
//Try to create a new entity with same data
oODataModel.create('/PersDataSet', entity, null, function(){
alert("Create successful");
},function(oError){
alert("Create failed", oError);
});
};
oODataModel.read("/PersDataSet", null, [], true, handleRead, handleReadE);
In the gateway error log, an xml parsing error appears. In this log, we can see the request data and it can be seen that the dates are transported with String types. These dates are defined in the service as DateTimes so the request is rejected.
Example:
<m:properties>
<d:Pernr m:type="Edm.String">00000001</d:Pernr>
<d:Endda m:type="Edm.String">9999-12-31T00:00:00</d:Endda>
<d:Begda m:type="Edm.String">1979-05-23T00:00:00</d:Begda>
When the entity is read, the backend does not send any type information. It sends like the following example:
<m:properties>
<d:Pernr>72010459</d:Pernr>
<d:Endda>9999-12-31T00:00:00</d:Endda>
<d:Begda>1876-07-21T00:00:00</d:Begda>
And, indeed, if we try to save the same info without the type=".." it works. So the problem are the incorrect types ODataModel.create adds to the xml.
My question is:
Can I tell ODataModel.create to not add this type info? It is not doing a good job inferring the types.
Can anyone share an example reading and writing dates through odata?
Thank you very much in advance.
the data returned from oODataModel.read is raw, before you post you need to parse it
var handleRead = function (oEvent){
//Get the data read from backend
entity = oEvent.results[0];
var newEntity = jQuery.extend({},entity);
delete newEntity.__metadata;
newEntity.Begda = new Date(entity.Begda);
newEntity.Endda = new Date(entity.Endda);
//Try to create a new entity with same data
oODataModel.create('/PersDataSet', newEntity, null, function(){
why not use json instead of xml?
Thanks all for the help.
We got this working accounting for the following:
The problem of the wrong types appended to the attributes comes from the read itself. The object returned by read has a __metadata attribute which describes the values. In this object the dates are set with type=edm.string, even when the service says they are DateTime. To me this is a bug of the .read function.
When trying to use the same object to save, create sees the __metatada on the entry and uses those values, producing type edm.string type for the dates. This caused the request to be rejected. Manually changing these __metadata.properties...type to Edm.DateTime makes it work.
In the end, we did the following:
Dates are parsed manually from the Odata response, creating a js Date
object from the strings in format "yyyy-mm-ddT00:00:00", to make it work with control bindings. When we want to save, the reverse is done.
The object to be created is a new object with
only the attributes we care (no __metadata)

Categories

Resources