poloniex API request BUY SELL CANCEL cause error = "Invalid API key/secret pair."; - api

Hello To every one I am writing in swift 3 trading app. I have problem only with 3 commands buy sell and cancel , that ones cause error = "Invalid API key/secret pair."; others like returnOpenOrders , returnTradehistory returnBalances works fine and returns proper values.
That is may request function :
func getRawJSON(paramss:[String : Any]){
var paramss1:[String:Any] = [:]
let APIURL = "https://poloniex.com/tradingApi"
let timeNowInt = Int(NSDate().timeIntervalSince1970 ) * 10000000
var zdanie2:String! = ""
for (x,y) in paramss{
paramss1[x]=y
}
paramss1["nonce"]=timeNowInt
for (x,y) in paramss{
if (zdanie2 == "")
{zdanie2="\(x)=\(y)"
}
else
{
zdanie2=zdanie2+"&"+"\(x)=\(y)"
}
}
zdanie2=zdanie2+"&nonce=\(timeNowInt)"
let array: [UInt8] = Array(zdanie2.utf8)
let hmac: Array<UInt8> = try! HMAC(key: secretKey!.utf8.map({$0}), variant: .sha512).authenticate(array)
let hmacData = Data(bytes: hmac).toHexString()
let headers = ["Key": publicKey!,"Sign": hmacData] as [String : String]
request(APIURL,method: .post,parameters: paramss1,headers:headers).responseJSON {
response in
print(response)
print(response.request)
}
}
Here is my buy/sell function :
func buy(currencyPair:String,rate:Double,amount:Double){
return self.getRawJSON( paramss: ["command":"buy","currencyPair":currencyPair,"rate":rate ,"amount":amount])
}
func sell(currencyPair:String,rate:Double,amount:Double){
return self.getRawJSON( paramss: ["command":"sell","currencyPair":currencyPair,"rate": rate ,"amount":amount])
}
The output from headers parameters(var paramss1 ) is :
["amount": 2.0, "command": "sell", "nonce": 15308121310000000, "currencyPair": "BTC_XRP", "rate": 7.6000000000000004e-05]
The array for sign is :
amount=2.0&command=sell&currencyPair=BTC_XRP&rate=7.6e-05&nonce=15308121310000000
I really dont know what is wrong
Can you help with this problem ??

rate value is invalid.
rate and amount values must be like 1, 1.1, 1.00000001.
Invalid request:
amount=2.0&command=sell&currencyPair=BTC_XRP&rate=7.6e-05&nonce=15308121310000000
Valid request:
command=sell&amount=2.0&&currencyPair=BTC_XRP&rate=7.000006&nonce=15308121310000000

Related

API call from google sheets is too long

I am trying to write a script in google sheets to update my 3commas bots. The API requires a number of mandatory fields are passed even when there's only 1 item that needs to be updated.
The code I have is below and it uses the values already read from the platform updating only the base_order_volume value. This works perfectly except for when the pairs value is long (more the 2k chars) and then I get an error from the UrlFetchApp call because the URL is too long.
var sheet = SpreadsheetApp.getActiveSheet();
var key = sheet.getRange('F4').getValue();
var secret = sheet.getRange('F5').getValue();
var baseUrl = "https://3commas.io";
var editBots = "/ver1/bots/"+bots[botCounter].id+"/update";
var patchEndPoint = "/public/api"+editBots+"?";
.
.
[loop around values in sheet]
.
.
var BaseOrder=Number(sheet.getRange(rowCounter,12).getValue().toFixed(2));
var botParams = {
"name": bots[botCounter].name,
"pairs": bots[botCounter].pairs,
"max_active_deals": bots[botCounter].max_active_deals,
"base_order_volume": BaseOrder,
"take_profit": Number(bots[botCounter].take_profit),
"safety_order_volume": bots[botCounter].safety_order_volume,
"martingale_volume_coefficient": bots[botCounter].martingale_volume_coefficient,
"martingale_step_coefficient": Number(bots[botCounter].martingale_step_coefficient),
"max_safety_orders": bots[botCounter].max_safety_orders,
"active_safety_orders_count": Number(bots[botCounter].active_safety_orders_count),
"safety_order_step_percentage": Number(bots[botCounter].safety_order_step_percentage),
"take_profit_type": bots[botCounter].take_profit_type,
"strategy_list": bots[botCounter].strategy_list,
"bot_id": bots[botCounter].id
};
var keys = Object.keys(botParams);
var totalParams = keys.reduce(function(q, e, i) {
q += e + "=" + encodeURIComponent(JSON.stringify(botParams[e])) + (i != keys.length - 1 ? "&" : "");
return q;
},endPoint);
var signature = Utilities.computeHmacSha256Signature(totalParams, secret);
signature = signature.map(function(e) {return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2)}).join("");
var headers = {
'APIKEY': key,
'Signature': signature,
};
try {
var params = {
'method': 'PATCH',
'headers': headers,
'muteHttpExceptions': true
};
var response = JSON.parse(UrlFetchApp.fetch(baseUrl + totalParams, params).getContentText());
I have tried to set the botParams as a payload in the params but when I do the signature is incorrect.
I anyone knows how to use sheets to make a call using extensive length of parameters I'd appreciate any help at all
Some sample data for the bots array would be
{
"name": "TestBot",
"base_order_volume": 0.001,
"take_profit": 1.5,
"safety_order_volume": 0.001,
"martingale_volume_coefficient": 2,
"martingale_step_coefficient": 1,
"max_safety_orders": 1,
"active_safety_orders_count": 1,
"safety_order_step_percentage": 2.5,
"take_profit_type": "total",
"stop_loss_percentage": 0,
"cooldown": 0,
"pairs": ["BTC_ADA","BTC_TRX"],
"trailing_enabled":"true",
"trailing_deviation":0.5,
"strategy_list": [{"strategy":"cqs_telegram"}]
}
Thanks in advance
I'd consider using a Cloud Function to either do the heavy lifting, or, if you're worried about costs, use it as a proxy. You can then call the cloud function from Google Sheets. Cloud Functions can be written in whatever language you're most comfortable with, including Node.
Check the GCP pricing calculator to see what the cost would be. For many cases it would be completely free.
This should give you a sense of how to use cloud functions for CSV creation:
https://codelabs.developers.google.com/codelabs/cloud-function2sheet#0
Here is a SO question with an answer that explains how to query cloud functions with authentication.

I am trying to get data over an OpenWeather API in Rust but I am facing some iusse regarding parsing I guess

extern crate openweather;
use openweather::LocationSpecifier;
static API_KEY: &str = "e85e0a3142231dab28a2611888e48f22";
fn main() {
let loc = LocationSpecifier::Coordinates {
lat: 24.87,
lon: 67.03,
};
let weather = openweather::get_current_weather(loc, API_KEY).unwrap();
print!(
"Right now in Minneapolis, MN it is {}K",
weather.main.humidity
);
}
error : thread 'main' panicked at 'called Result::unwrap() on an
Err value: ErrorReport { cod: 0, message: "Got unexpected response:
\"{\\"coord\\":{\\"lon\\":67.03,\\"lat\\":24.87},\\"weather\\":[{\\"id\\":803,\\"main\\":\\"Clouds\\",\\"description\\":\\"broken
clouds\\",\\"icon\\":\\"04n\\"}],\\"base\\":\\"stations\\",\\"main\\":{\\"temp\\":294.15,\\"pressure\\":1018,\\"humidity\\":60,\\"temp_min\\":294.15,\\"temp_max\\":294.15},\\"visibility\\":6000,\\"wind\\":{\\"speed\\":5.1,\\"deg\\":30},\\"clouds\\":{\\"all\\":70},\\"dt\\":1574012543,\\"sys\\":{\\"type\\":1,\\"id\\":7576,\\"country\\":\\"PK\\",\\"sunrise\\":1573955364,\\"sunset\\":1573994659},\\"timezone\\":18000,\\"id\\":1174872,\\"name\\":\\"Karachi\\",\\"cod\\":200}\""
}
The issue is a JSON parsing error due to the deserialized struct not matching OpenWeather's JSON, perhaps the API recently added this? With your example, the OpenWeatherCurrent struct is missing timezone.
But it looks like there is an open PR that will fix this, you can test it by doing the following:
Change your Cargo.toml dependency to openweather = { git = "https://github.com/caemor/openweather" }.
The PR author has also updated the get_current_weather signature so you'll need to change lines 2, 10 to the following:
use openweather::{LocationSpecifier, Settings};
let weather = openweather::get_current_weather(&loc, API_KEY, &Settings::default()).unwrap();

How does ibm - mobile first get mobile number from security context?

I am following "isRegistered" api from this sample code. I did not understand how we get phone number from security context.
The API that I want to use is:
#Path("/isRegistered")
#GET
#Produces("application/json")
#OAuthSecurity(enabled = true)
#ApiOperation(value = "Check if a phone number is registered",
notes = "Check if a phone number is registered",
httpMethod = "GET",
response = Boolean.class
)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "OK",
response = String.class),
#ApiResponse(code = 401, message = "Not Authorized",
response = String.class),
#ApiResponse(code = 500, message = "Cannot check if phone number is registered",
response = String.class)
})
public Boolean isRegistered() {
//Getting client data from the security context
ClientData clientData = securityContext.getClientRegistrationData();
if (clientData == null) {
throw new InternalServerErrorException("This check allowed only from a mobile device.");
}
String number = clientData.getProtectedAttributes().get(SMSOTPSecurityCheck.PHONE_NUMBER);
return number != null && !number.trim().equals("");
}
How does the security context have the client phone number?
There is a client project as well in this sample. Please refer to the complete sample.
Within the client side logic here, the user is asked to provide the phone number , which is sent to the server in an adapter call:
MainViewController.codeDialog("Phone Number", message: "Please provide your phone number",isCode: true) { (phone, ok) -> Void in
if ok {
let resourseRequest = WLResourceRequest(URL: NSURL(string:"/adapters/smsOtp/phone/register/\(phone)")!, method:"POST")
.....
Now in the adapter code path #Path("/register/{phoneNumber}") notice the following code:
clientData.getProtectedAttributes().put(SMSOTPSecurityCheck.PHONE_NUMBER, phoneNumber);
securityContext.storeClientRegistrationData(clientData);
This is how the phone number made it to the security context.
Run the sample and use a tool such as Wireshark to analyze the data flow between client and server.

how to Pass Raw Json to post request in Swift?

Hi I am new to swift please spare me.
I need to post to particular API but the api is not a fan of key value pair the api expect raw json as post data
I use this library here to make post request.
this is my code
func postItem(itemname: String, itemnumber: Int, itemcode:String, url:String, baseURL:String, completion: (result: Dictionary<String, AnyObject>) -> ()){
var dict: Dictionary<String, AnyObject>!
var params: Dictionary<String,AnyObject> = ["parentItem": ["itemname":itemname,"itemnumber":itemnumber,"itemcode":code]]
let data = NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.PrettyPrinted, error: nil)
let string = NSString(data: data!, encoding: NSUTF8StringEncoding)
var request = HTTPTask()
request.requestSerializer = JSONRequestSerializer()
request.requestSerializer.headers[headerKey] = getToken() //example of adding a header value
request.POST(url, parameters: params, success: {(response: HTTPResponse) in
if response.responseObject != nil {
let data = response.responseObject as NSData
var error: NSError?
dict = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as Dictionary<String, AnyObject>;
completion(result: dict)
}
},failure: {(error: NSError, response: HTTPResponse?) in
dict = ["error" : "error" ]
completion(result: dict)
})
}
i need to pass this kind of raw json in api
eg. {"parentItem": {"itemname":"Cocoa","itemnumber":123,"itemcode":"cocoa-12-A"}}
but when I println my params because it is dictionary it generate something like
["parentItem": ["itemname"="Cocoa"; "itemnumber"=123; "itemcode"="cocoa-12-A"]]
I just couldn't convert the params to JSON because the library I'm using is expecting dictionary and I'm having a hard time creating my own class.
could anyone help me? any comments and suggestion would do. Thanks in advance.
Why don't use Alamofire framework ? It's pretty good and sends standard json

How to pass same parameter with different value

I am trying the following API using Alamofire, but this API has multiple "to" fields. I tried to pass an array of "to" emails as parameters. It shows no error but did not send to all emails. API is correct, I tested that from terminal. Any suggestions will be cordially welcomed.
http -a email:pass -f POST 'sampleUrl' from="email#email.com" to="ongkur.cse#gmail.com" to="emailgmail#email.com" subject="test_sub" bodyText="testing hello"
I am giving my code:
class func sendMessage(message:MessageModel, delegate:RestAPIManagerDelegate?) {
let urlString = "http://localhost:8080/app/user/messages"
var parameters = [String:AnyObject]()
parameters = [
"from": message.messageFrom.emailAddress
]
var array = [String]()
for to in message.messageTO {
array.append(to)
}
parameters["to"] = array
for cc in message.messageCC {
parameters["cc"] = cc.emailAddress;
}
for bcc in message.messageBCC {
parameters["bcc"] = bcc.emailAddress;
}
parameters["subject"] = message.messageSubject;
parameters["bodyText"] = message.bodyText;
Alamofire.request(.POST, urlString, parameters: parameters)
.authenticate(user: MessageManager.sharedInstance().primaryUserName, password: MessageManager.sharedInstance().primaryPassword)
.validate(statusCode: 200..<201)
.validate(contentType: ["application/json"])
.responseJSON {
(_, _, jsonData, error) in
if(error != nil) {
println("\n sendMessage attempt json response:")
println(error!)
delegate?.messageSent?(false)
return
}
println("Server response during message sending:\n")
let swiftyJSONData = JSON(jsonData!)
println(swiftyJSONData)
delegate?.messageSent?(true)
}
}
First of all if you created the API yourself you should consider changing the API to expect an array of 'to' receivers instead of multiple times the same parameter name.
As back2dos states it in this answer: https://stackoverflow.com/a/1898078/672989
Although POST may be having multiple values for the same key, I'd be cautious using it, since some servers can't even properly handle that, which is probably why this isn't supported ... if you convert "duplicate" parameters to a list, the whole thing might start to choke, if a parameter comes in only once, and suddendly you wind up having a string or something ...
And I think he's right.
In this case I guess this is not possible with Alamofire, just as it is not possible with AFNetworking: https://github.com/AFNetworking/AFNetworking/issues/21
Alamofire probably store's its POST parameter in a Dictionary which doesn't allow duplicate keys.