Why does Base64.encode() not reset memory after being called? - memory-management

Ok, so this is my very first question on stack exchange and I am new to solidity.
I am trying to create an ERC 721 contract that emits a url containing the address and (hashed) tokenId of minted NFTs. I noticed that the URLs emitted become larger every time the mint function is called.
I narrowed down the problem to Base64.encode(), but am stuck. I searched but can't seem to find an answer, possibly because I do not know what to search for.
Take the contract below. It emits a custom URL that includes a data field created through Base64.encode(). I would expect the emitted URL to be the same length every time, as memory is wiped between calls.
But... each time the Mint function is called, the data field includes data from previous calls.
The first time I call Mint() the emitted reads as follows: "someURL.com?MHg5ZDgzZTE0MDMzMDc1OGE4ZmZkMDdmOGJkNzNlODZlYmNhOGE1Njky"
The second time I call Mint() the emitted is longer:
"someURL.com?MHg5ZDgzZTE0MDMzMDc1OGE4ZmZkMDdmOGJkNzNlODZlYmNhOGE1Njky?MHg5ZDgzZTE0MDMzMDc1OGE4ZmZkMDdmOGJkNzNlODZlYmNhOGE1Njky"
And on it goes evertime I call Mint(). Memory seems to be retained. Why? What am I missing here?
Many many thanks for any help or pointers!
pragma solidity ^0.8.4;
import "#openzeppelin/contracts/utils/Strings.sol";
import "#openzeppelin/contracts/utils/Base64.sol";
contract URLMemory {
using Strings for uint256;
string customURL = "someURL.com";
event CustomURLIssued(string customURL);
function issueCustomURL() public returns (string memory){
customURL = string(
abi.encodePacked(
customURL,
"?",
Base64.encode( abi.encodePacked( Strings.toHexString(address(this)) )
)
));
return customURL;
}
function Mint() public {
emit CustomURLIssued(issueCustomURL());
}
}

customURL = string(
abi.encodePacked(
customURL,
"?",
Base64.encode(abi.encodePacked(Strings.toHexString(address(this))))
)
);
This snippet assigns a new value to customURL, and the new value consists of following parts:
the previous value of customURL
? string literal
and the encoded address
So each time you execute this snippet, it effectively appends the customURL with the new values.
Simplified example when we omit the Base64 encoding.
customURL = string(
abi.encodePacked(
customURL,
"?"
)
);
Initial customURL value = A
After first run it becomes A?. Second run A??. Third run A???. And so on.
If you want to keep the someURL.com prefix and only add the ? and encoded value for each token, you can just return the newly generated value without assigning it back to customURL.
function issueCustomURL() public view returns (string memory){
return string(
abi.encodePacked(
customURL,
"?",
Base64.encode( abi.encodePacked( Strings.toHexString(address(this)) )
)
));
}
Note: If you upgrade to Solidity 0.8.12 or later, you can use native function string.concat() instead of connecting the strings with abi.encodePacked().
string.concat(customURL, "?", encoded)

Related

Powerautomate Parsing JSON Array

I've seen the JSON array questions here and I'm still a little lost, so could use some extra help.
Here's the setup:
My Flow calls a sproc on my DB and that sproc returns this JSON:
{
"ResultSets": {
"Table1": [
{
"OrderID": 9518338,
"BasketID": 9518338,
"RefID": 65178176,
"SiteConfigID": 237
}
]
},
"OutputParameters": {}
}
Then I use a PARSE JSON action to get what looks like the same result, but now I'm told it's parsed and I can call variables.
Issue is when I try to call just, say, SiteConfigID, I get "The output you selected is inside a collection and needs to be looped over to be accessed. This action cannot be inside a foreach."
After some research, I know what's going on here. Table1 is an Array, and I need to tell PowerAutomate to just grab the first record of that array so it knows it's working with just a record instead of a full array. Fair enough. So I spin up a "Return Values to Virtual Power Agents" action just to see my output. I know I'm supposed to use a 'first' expression or a 'get [0] from array expression here, but I can't seem to make them work. Below are what I've tried and the errors I get:
Tried:
first(body('Parse-Sproc')?['Table1/SiteConfigID'])
Got: InvalidTemplate. Unable to process template language expressions in action 'Return_value(s)_to_Power_Virtual_Agents' inputs at line '0' and column '0': 'The template language function 'first' expects its parameter be an array or a string. The provided value is of type 'Null'. Please see https://aka.ms/logicexpressions#first for usage details.'.
Also Tried:
body('Parse-Sproc')?['Table1/SiteconfigID']
which just returns a null valued variable
Finally I tried
outputs('Parse-Sproc')?['Table1']?['value'][0]?['SiteConfigID']
Which STILL gives me a null-valued variable. It's the worst.
In that last expression, I also switched the variable type in the return to pva action to a string instead of a number, no dice.
Also, changed 'outputs' in that expression for 'body' .. also no dice
Here is a screenie of the setup:
To be clear: the end result i'm looking for is for the system to just return "SiteConfigID" as a string or an int so that I can pipe that into a virtual agent.
I believe this is what you need as an expression ...
body('Parse-Sproc')?['ResultSets']['Table1'][0]?['SiteConfigID']
You can see I'm just traversing down to the object and through the array to get the value.
Naturally, I don't have your exact flow but if I use your JSON and load it up into Parse JSON step to get the schema, I am able to get the result. I do get a different schema to you though so will be interesting to see if it directly translates.

How to make Get Request with Request param in Postman

I have created an endpoint that accepts a string in its request param
#GetMapping(value = "/validate")
private void validateExpression(#RequestParam(value = "expression") String expression) {
System.out.println(expression);
// code to validate the input string
}
While sending the request from postman as
https://localhost:8443/validate?expression=Y07607=Curr_month:Y07606/Curr_month:Y07608
// lets say this is a valid input
console displays as
Y07607=Curr_month:Y07606/Curr_month:Y07608 Valid
But when i send
https://localhost:8443/validate?expression=Y07607=Curr_month:Y07606+Curr_month:Y07608
//which is also an valid input
console displays as
Y07607=Curr_month:Y07606 Curr_month:Y07608 Invalid
I am not understanding why "+" is not accepted as parameter.
"+" just vanishes till it reaches the api! Why?
I suggest to add this regular expression to your code to handle '+' char :
#GetMapping(value = "/validate")
private void validateExpression(#RequestParam(value = "expression:.+") String expression) {
System.out.println(expression);
// code to validate the input string
}
I didn't find any solution but the reason is because + is a special character in a URL escape for spaces. Thats why it is replacing + with a " " i.e. a space.
So apparently I have to encode it from my front-end
Its wise to encode special characters in a URL. Characters like \ or :, etc.
For + the format or value is %2. You can read more about URL encoding here. This is actually the preferred method because these special characters can sometimes cause unintended events to occur, like / or = which can mean something else in the URL.
And you need not worry about manually decoding it in the backend or server because it is automatically decoded, in most cases and frameworks. In your case, I assume you are using Spring Boot, so you don't need to worry about decoding.

how to get ask and bid from .Net ClrWrapper

I am using MetaTrader4.Manager.Wrapper
I want to get all currency (Symbol in MT4) and their bid & ask from MT4. I tried using :
public IList<Symbol> Get()
{
using (var metatrader = new ClrWrapper(new ConnectionParameters
{
Login = serverdata.Login,
Password = serverdata.Password,
Server = serverdata.Server
}, serverdata.path))
{
var Refresh = metatrader.SymbolsRefresh();
IList<Symbol> Live = metatrader.SymbolsGetAll();
return Live;
}
}
From the code i got the Name : AUDCAD, AUDCHF, EURCHF, etc, but BidTickValue and AskTickValue return 0.0.
I tried using this answer but the Symbol return null and Bid return 0.
Is there another way to get the Name and Bid and Ask value?
And what is Pumping Mode means?
Thank you before
Pumping is MT4 mode, when you subscribe to different events and MT4 server sends you updates, without requesting it manually.
For example: quotes, trades, users.
SymbolsGetAll will return you quotes only when you in pumping mode, and it will return latest received quote.
If you are not going to use pumping mode, you can get latest quote user ChartRequest method, but it will be much slower.
You can get the quotes with bid and ask directly without manager API.
Simply you can send a socket to MT4 server.
Here is an example:
// 1. Start Session.
$ptr=fsockopen('127.0.0.1',443);
// error check
if (!$ptr){
echo "Connection error";
exit;
}
// 2. Send request to MT4
fputs($ptr,"WQUOTES-EURUSD,GBPUSD,USDJPY,\nQUIT\n");
// 3. Reading and processing server responses
while(!feof($ptr))
{
// read line of symbols
$line=fgets($ptr,128);
// the symbol of the end of result transfer
if($line=="end\r\n") break;
// process
print $line;
}
// 4. Session completion
fclose($ptr);
The above will print the quotes in this format: direction symbol bid ask date time.

SendKeys() is adding default value (issue) + datetime value sent

basically the issue is taking place at the moment when I send some value which is appended to a default value '01/01/2000' somehow. I've tried different ways to do this without succeed, I've used these exact lines in other script and it worked but I don't know why this isn't working here. Please find below the last code I used followed by the picture with the issue displayed.
var targetStartDate = browser.driver.findElement(by.id('StartDate'));
targetStartDate.clear().then(function () {
targetStartDate.sendKeys('09/01/2016');
})
example of the issue
Thanks in advance for any response.
You can try issuing clear() call before sending keys:
targetStartDate.clear();
targetStartDate.sendKeys('09/01/2016');
The other option would be to select all text in the input prior to sending keys:
// protractor.Key.COMMAND on Mac
targetStartDate.sendKeys(protractor.Key.chord(protractor.Key.CONTROL, "a"));
targetStartDate.sendKeys('09/01/2016');
I have encountered this same issue before. There is an input mask formatting the input in the field. In order to solve this, you must write your test as if it were the actual user, with the formatting in mind:
var targetStartDate = browser.driver.findElement(by.id('StartDate'));
// Remove the forward slashes because the input field takes care of that.
var inputDate = '09012016';
targetStartDate.clear();
// Loop through each character of the string and send it to the input
// field followed by a delay of 250 milliseconds to give the field
// enough time to format the input as you keep sending keys.
for (var i = 0; i < inputDate.length; i++) {
targetStartDate.sendKeys(inputDate[i]);
browser.driver.sleep(250);
}
Depending on the latency of the site and performance, you may either need to decrease the 250 millisecond delay, or be able to decrease it.
Hope this helps!

How to return localized content from WebAPI? Strings work but not numbers

Given this ApiController:
public string TestString() {
return "The value is: " + 1.23;
}
public double TestDouble() {
return 1.23;
}
With the browser's language set to "fr-FR", the following happens:
/apiController/TestString yields
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">The value is: 1,23</string>
/apiController/TestDouble yields
<double xmlns="http://schemas.microsoft.com/2003/10/Serialization/">1.23</double>
I would expect TestDouble() to yield 1,23 in the XML. Can anyone explain why this isn't the case and, more importantly, how to make it so that it does?
It is because the conversion from double to string happens at different stage for each API. For the TestString API, double.ToString() is used to convert the number to a string using CurrentCulture of the current thread and it happens when the TestString method is called. Meanwhile, the double number which is returned by TestDouble is serialized to string during the serialization step which uses GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Culture.
In my opinion, both should use InvariantCulture. On the consumer side, the values will be parsed and be formatted with the correct culture.
Update: this is only used for JsonFormatter. XmlFormatter doesn't have such a setting.
Update 2:
It seems (decimal) numbers need special converter to make it culture-aware:
Handling decimal values in Newtonsoft.Json
Btw, if you want o change data format per action/request, you can try the last piece of code of the following link: http://tostring.it/2012/07/18/customize-json-result-in-web-api/

Resources