Provider not set or invalid. How to interact with smart contract without wallet? - blockchain

I am developing a Web3 App using Solidity, smart contract is working perfect, after deploying it to web server, The app is working flawless on my PC but I faced an issue on my browsers that don't have Metamask wallet.
Error:
Error: Provider not set or invalid
at Object.InvalidProvider (errors.js:39:16)
at f.send (index.js:145:32)
at s (index.js:624:42)
at a.n [as getId] (index.js:656:13)
at Web3Client.js:197:39
at f (regeneratorRuntime.js:86:17)
at Generator._invoke (regeneratorRuntime.js:66:24)
at Generator.next (regeneratorRuntime.js:117:21)
at Ne (asyncToGenerator.js:3:20)
at a (asyncToGenerator.js:25:9)
React Code:
export const init = async () => {
let provider = window.ethereum;
if (typeof provider !== 'undefined') {
}
const web3 = new Web3(provider);
const networkId = await web3.eth.net.getId();
erc20Contract = new web3.eth.Contract(
erc20Abi,
addr
);
isInitialized = true;
};
What is the best and minimal way to interact with Smartcontracts without Wallet?

You can create account on https://infura.io then you get api key to communicate with blockchain. Copy url from infura, in result you should get response from provider. const web3 = new Web3('https://mainnet.infura.io/v3/YOUR-API-KEY ');

MetaMask comes with a built-in HTTPProvider for Infura JSON-RPC API.
You can register to any of the free JSON-RPC API provider services and get a personal JSON-RPC endpoint with an API key. Alternatively you can run your own Ethereum node.
You can also reverse engineer MetaMask and get their API key out from its JavaScript files.

Related

Using generated on the server AccessToken to connect to GCP Text to Speech

I would like to be able to connect to GCP Text to Speech from a react.js front-end using an access token generated on the server. I adapted the code from the linked reply to produce an access token. However, I was not able to find in the docs how to use that token to connect from the front-end to GCP.
For simplicity, I would like to begin with modifying the linked working node.js example from the docs to use the hardcoded access token instead of the Default Credentials File to connect with the service.
Here is my attempt (compared to the example, only the construction of client is modified):
'use strict';
function main() {
// [START tts_quickstart]
// Imports the Google Cloud client library
const textToSpeech = require('#google-cloud/text-to-speech');
// Import other required libraries
const fs = require('fs');
const util = require('util');
// Creates a client
const client = new textToSpeech({tk: 'ya29.c.Kp8BCQj<etc.>'}).TextToSpeechClient();
async function quickStart() {
// The text to synthesize
const text = 'hello, world!';
// Construct the request
const request = {
input: {text: text},
// Select the language and SSML voice gender (optional)
voice: {languageCode: 'en-US', ssmlGender: 'NEUTRAL'},
// select the type of audio encoding
audioConfig: {audioEncoding: 'MP3'},
};
// Performs the text-to-speech request
const [response] = await client.synthesizeSpeech(request);
// Write the binary audio content to a local file
const writeFile = util.promisify(fs.writeFile);
await writeFile('output.mp3', response.audioContent, 'binary');
console.log('Audio content written to file: output.mp3');
}
quickStart();
// [END tts_quickstart]
}
main(...process.argv.slice(2));
I get an error that textToSpeech is not a constructor. How can I fix this example to connect to GCP Text to Speech using the access token?
Unfortunately it is not possible to authenticate via access token using the Text-To-Speech Nodejs Client Library. The TextToSpeechClient in Node runtime only accepts credentials objects which can be found from service accounts.
Based from the SO example you included in your question, it generates the access token and uses it in Android. It makes sense since there are no client libraries for Android as of now, so the OP is using the Text-To-Speech REST API to create an HTTP request. Using HTTP request requires the access token to authenticate, thus the solution of the SO example.
My suggestions are the following:
Adapt the solution similar to the SO example which is sending request via HTTP so you can use access token for authentication.
Use a different programming language like Python (seems unlikely since you are using React). It is possible in Python Client Library to use access token for authentication since it accepts credentials object.
Also just to add you are passing parameters incorrectly on your client object. It should be const client = new textToSpeech.TextToSpeechClient(object);

SignalR returns "Connection ID required" when ran in an AWS ECS container

I am trying to get a .Net Core 3.1 SignalR Web API with an Angular front end to work with websockets.
The code works perfectly fine when ran locally, either from within in the IDE or via docker run. However, once the code gets deployed to an ECS instance in AWS behind an API Gateway the web sockets refuse to connect.
I setup my mappings like so:
app.UsePathBase("/ui");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
"default",
"{controller}/{action=Index}/{id?}")
.RequireCors(PolicyName);
endpoints.MapHub<SessionHub>("/ws/session");
endpoints.MapHub<SessionsHub>("/ws/sessions");
});
And on the client I connect to the hub like so:
this.sessionsHubConnection = new HubConnectionBuilder()
.withUrl(`${window.origin}/ws/sessions`, {
skipNegotiation: true,
transport: HttpTransportType.WebSockets,
accessTokenFactory: () => this.getAccessToken()
})
.withAutomaticReconnect()
.build();
The following Fiddler trace shows the initial HTTP request to initialize the websocket connection and the error being returned by kestrel.
I tweaked my web socket middleware for handling the access token to also Console.Write some additional debugging statements that I think might prove insightful:
public async Task Invoke(HttpContext httpContext)
{
var request = httpContext.Request;
Console.WriteLine($"Starting connection id: {httpContext.Connection.Id}");
// web sockets cannot pass headers so we must take the access token from query param and
// add it to the header before authentication middleware runs
if (request.Path.StartsWithSegments("/ws", StringComparison.OrdinalIgnoreCase)
&&
request.Query.TryGetValue("access_token", out var accessToken))
{
request.Headers.Add("Authorization", $"Bearer {accessToken}");
}
try
{
var sb = new StringBuilder();
sb.AppendLine($"Connection Id: {httpContext.Connection.Id}");
Console.WriteLine(sb.ToString());
await _next(httpContext);
sb = new StringBuilder();
sb.AppendLine($"Status code {httpContext.Response.StatusCode}"); <-- this line
sb.AppendLine($"Connection Id: {httpContext.Connection.Id}"); <-- and this line
Console.WriteLine(sb.ToString());
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
throw;
}
}
And in the AWS logs you can see that the connection Id is present but is being ignored by the EndpointMiddleware(?) for some reason.
Any idea what could be causing this? Two ideas I have yet to be able to rule out are:
The HTTP/S termination at our API gateway is confusing Kestrel since the browser client is building the socket request under HTTPS, but as far as Kestrel is concerned everything is communicating over HTTP?
app.UsePathBase("/ui"); is confusing Kestrel and all the web socket paths should actually be /ui/ws/session?

Microsoft C++ Rest SDK for Graph APIs

I am trying out Microsoft's C++ Rest SDK (https://microsoft.github.io/cpprestsdk/index.html) to invoke Graph APIs but it has been a struggle so far.
In C# I can complete my tasks in a few lines of code. For example, refer following code from a Microsoft tutorial:
AuthenticationConfig config = AuthenticationConfig.ReadFromJsonFile("appsettings.json");
bool isUsingClientSecret = AppUsesClientSecret(config);
IConfidentialClientApplication app;
if (isUsingClientSecret)
{
app = ConfidentialClientApplicationBuilder.Create(config.ClientId)
.WithClientSecret(config.ClientSecret)
.WithAuthority(new Uri(config.Authority))
.Build();
}
string[] scopes = new string[] { $"{config.ApiUrl}.default" };
AuthenticationResult result = null;
try
{
result = await app.AcquireTokenForClient(scopes)
.ExecuteAsync();
}
catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011"))
{
}
// config.ApiUrl is set to "graph.microft.com"
if (result != null)
{
var httpClient = new HttpClient();
var apiCaller = new ProtectedApiCallHelper(httpClient);
await apiCaller.CallWebApiAndProcessResultASync($"{config.ApiUrl}v1.0/users", result.AccessToken, Display);
}
Now for cross-platform support, I need to develop similar functionality in C++ and for this purpose, we are exploring C++ Rest SDK from Microsoft. But I am unable to find any good examples to achieve a simple thing like providing client ID, client secret to get access token and to authorize.
Please let me know if anyone has come across any example / link to achieve the same.
Here you have some code for oauth 2.0 in Dropbox, Linkedin and MS Live scope:
https://github.com/microsoft/cpprestsdk/blob/master/Release/samples/Oauth2Client/Oauth2Client.cpp
Other samples within C++ Rest SDK:
https://github.com/microsoft/cpprestsdk/tree/master/Release/samples
First of all, you have to distinguish:
1. MS Graph authentication - which is, in fact, Azure Access Directory/Microsoft identity platform authentication, based on oauth 2.0 (short name: MSAL)
2. Accessing the MS Graph API using access token from the authentication process (in the standard process you should use MS Graph SDK)
For the C++ there is no MSAL or SDK library.
So - for authentication, you should use oauth 2.0 example which I pasted above.
Because you need to write everything on your own, please read deeply docs about authentication for MS Graph
https://learn.microsoft.com/en-us/graph/auth/
Here you can watch all the needed endpoints, secrets etc. for sample Postman calls:
https://learn.microsoft.com/en-us/graph/use-postman#set-up-on-behalf-of-api-calls
https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-13-postman-to-make-microsoft-graph-calls/
In the URLs there are the following variables used:
Callback URL: https://app.getpostman.com/oauth2/callback
Auth URL: https://login.microsoftonline.com/**TENANTID**/oauth2/v2.0/authorize
Access Token URL: https://login.microsoftonline.com/**TENANTID**/oauth2/v2.0/token
Client ID: CLIENTID
Client Secret: CLIENTSECRET
Scope: https://graph.microsoft.com/.default
State: RANDOMSTRING
For the API calls, read about Microsoft Graph REST API v1.0 reference
https://learn.microsoft.com/en-us/graph/api/overview?toc=./ref/toc.json&view=graph-rest-1.0

How to attach X509Certificate2 to webservice (Apple GSX / C# specific)

Apple released their New Generation WSDL on the 15 of August this year (2015) and the big change was that every call to the WSDL had to be validated with a certificate file.
I've done the process to get the certificate from Apple, and I've whitelisted our server IP, and I've even verified that I can get access to the service endpoint from our server by coding a simple interface using HttpWebRequest where I easily can attach the certificate using webRequest.ClientCertificates.Add(), so I know everything is ready for it to work.
But, my problem arises when I download the WSDL from https://gsxwsut.apple.com/apidocs/prod/html/WSArtifacts.html?user=asp
I import the WSDL into Visual Studio and when I try to make an instance of the client class, the only one I find is GsxWSEmeaAspPortClient, which seems to be correct as it has all the functions for authenticate and various tools, but it does not have ClientCertificates. It does have ClientCredentials which have ClientCertificate, but when I try to set the cert there, it's as tho it's never set.
I'm guessing the service code transmits the data via either HttpWebRequest or WebRequest, so if I just can get to the request code from my instance of the class (GsxWSEmeaAspPortClient) I can probably fix it, but I can't seem to get there.
I've looked at this question: How can I connect with Apple's GSX NewGeneration webservices with WCF? which suggests it really should be that easy, but I don't have the GsxWSEmeaAspService, only the GsxWSEmeaAspPortClient from my Visual Studio's generation of the WSDL.
If anyone has any ideas which can point me in any direction towards victory I'd be eternally grateful.
I'm using Visual Studio 2013 and the solution is .Net v4.5.1 if that makes any difference.
I've pasted new code here:
public void Authenticate() {
// Use custom binding with certificate authentication
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
// Create service endpoint
// Use proper endpoint address - eg. gsxapi.apple.com for production
EndpointAddress endpoint = new EndpointAddress("https://gsxapiit.apple.com/gsx-ws/services/emea/asp");
// Create new service
Apple.GsxWSEmeaAspPortClient service = new Apple.GsxWSEmeaAspPortClient(binding, endpoint);
// Set loaded certificate
service.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(
"[PathToContainerFromStep7].p12",
"[YourPasswordFromStep8]");
// Create authenticate request object
Apple.authenticateRequestType auth = new Apple.authenticateRequestType()
{
languageCode = "en",
userId = "[YourAppleServiceAccountNumber]",
userTimeZone = "[YourTimeZone]",
serviceAccountNo = "[YourSoldToNumber]"
};
// Authenticate to Apple GSX
Apple.authenticateResponseType session = service.Authenticate(auth);
// Assign your new session id object
userSessionId = new Apple.gsxUserSessionType() { userSessionId = session.userSessionId };
}

Getting "EndpointDisabled" from Amazon SNS

I'm using Amazon SNS. Notifications work well, but sometimes I get this error:
{
"message": "Endpoint is disabled",
"code": "EndpointDisabled",
"name": "EndpointDisabled",
"statusCode": 400,
"retryable": false
}
Maybe you know why.
You can create a new SNS topic such as push-notification-failures and then associate your APNS/APNS_SANDBOX applications' "Delivery Failures" event to it. Subscribe to the event via email (and confirm) and you'll get useful debugging information about failures. This can all be accomplished through the SNS console and doesn't require API calls to perform.
It is probably worth it to subscribe an HTTP endpoint to this SNS topic and record all delivery failures so you have historical data to work from and debug production issues.
For example a delivery FailureMessage of "Platform token associated with the endpoint is not valid" means that you're sending a message from APNS_SANDBOX to an APNS registered device or vice versa. This can mean that you have the wrong APNS settings for your build system. (We have a frustrating problem of developer built binaries using APNS_SANDBOX vs. TestFlight built binaries using APNS for local testing and QA which is what led me down this path.)
I have found 3 reasons so far:
Sometimes we mixed tokens from sandbox app.
User turn off notifications in phone settings.
User uninstalled the app.
These are regarding Iphons/Ipads.
There are few reasons why an end point can be disabled. I didn't see it documented anywhere (might have missed it), here's what I got from support:
You push to an endpoint but the token is invalid/expired. Tokens become invalid if:
It belongs to an app that is no more installed on the device.
If device has been restored from backup. This renders token invalid and your app should request a new token and update SNS endpoint token accordingly.
App has been re-installed on the same device. In case of Android, the app is assigned a new token. This happens as well with APNs but more often with Android.
In case of APNs, a wrong provisioning profile is selected in xCode. In this case notifications fail and device becomes disabled later after APNs feedback.
If mistakenly use a token for IOS development to IOS production app and vice versa.
If Apple for any reason invalidates your IOS push cert or someone revokes the push cert from itunes connect portal. This takes a few hours before device gets disabled.
Same with GCM if you update API key from Google developer console without updating the Platform application credentials in SNS.
You push to an APNs device endpoint but application has been disabled due to expired push certificate.
You push to GCM device endpoint however API key has been updated in Google developer console but not the SNS platform application credentials accordingly.
For Details, I recommend this excellent article which solves my problem
According to http://docs.aws.amazon.com/sns/latest/APIReference/API_Publish.html that means that the endpoint is disabled.
From http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/sns/model/SetEndpointAttributesRequest.html:
Enabled -- flag that enables/disables delivery to the endpoint. Message Processor will set this to false when a notification service indicates to SNS that the endpoint is invalid. Users can set it back to true, typically after updating Token.
"notification service" in this case is referring to Google's GCM, Apples APNS or Amazon's ADM.
I had the same issue.
This is what I did:
export the FULL CERTIFICATE from Keychain Access to a .p12 file
export the PRIVATE KEY from Keychange Access to a *private.p12 file
use openssl with the downloaded .cer file (from iOS Developer MemberCenter) to create a public .pem certificate
use openssl with the generated *private.p12 file to create a private .pem keyfile
In AWS SNS create a new Application. Give it a name. Choose Apple Development.
Choose the FULL CERTIFICATE from Keychain Access with a .p12 extension, and type in the passphrase you chose when exporting from Keychain Access
Copy the content of the public CERTIFICATE .pem file, to the textarea labelled "Certificate", including the starting and ending lines:
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
Copy only the part of the private key .pem file starting and ending with the following lines, to the textarea labelled "Private Key":
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
I use Cordova with phonegap-plugin-push 1.4.4, but it my issue had nothing to do with phonecap. Apart from a bit of confusion about the above, what finally did the trick for me, was to open up my project in XCode, find the Target for my project, and then enable Push Notifications. This automatically adds the "Push Notifications" entitlement to the app ID.. The next time the app is installed on your device, push notification should work. At least it did for me.
I hope this can save someone experiencing the same issue as me a 1/2 day of work! :)
Quick checklist before taking drastic measures:
Generate the Certificate Signing Request (CSR) using Keychain App.
Export the APNS certificate and its private key into a single p12 file using Keychain App.
When you create a new application in Amazon SNS, the platform must match the APNS environment (Development/Production on both sides).
When you request a device token, you must be in the right application (the application's bundle identifier matches the APNS certificate).
When you create a new platform endpoint in AWS SNS, the device token must be added to the right application (the good application certificate and the good Development/Production platform).
In my case I generated the CSR using a third party SSL tool. I obtained a valid certificate from Apple developer portal but without the private key. Then I tried Windows' certificate tool to export without great success. Waste of time. Start your Mac.
Then I used the AmazonMobilePush sample app to get a device token. Because the demo's bundle identifier doesn't match my certificate, the endpoint was invalid. At each SNS sending the endpoint became disabled (false). At the end the cause was obvious, but I still lose precious time.
If you get the error End Point is Disabled, use the code below to enable the endPoint and then Push Notification using Amazon credentials:
*//Enable Device*
var sns = new AmazonSimpleNotificationServiceClient("AwsAccesskeyId", "AwsSecrteAccessKey", RegionEndpoint.USWest1);
Dictionary<string, string> objDictCheckEndpointEnable = new Dictionary<string, string>();
objDictCheckEndpointEnable.Add("Enabled", "False");
sns.SetEndpointAttributes(new SetEndpointAttributesRequest
{
Attributes = objDictCheckEndpointEnable,
EndpointArn = "AwsEndPointArn" //This is Device End Point Arn
});
*//End*
For me, I was getting the "Platform token associated with the endpoint is not valid" because my SNS Platform Application Endpoints were not set up correctly. Specifically, the SNS console was not reading the credentials correctly from my .p12 file even though it contained the correct cert and private key. The solution, based on this post, was to create a second .p12 file that contained the cert and no key. I loaded the credentials from the first .p12 file, and then loaded the credentials second .p12 file. I could see the cert string change when I did so, and afterward I had no problems.
If you are creating a production endpoint, SNS will warn you about mismatched certs, but it does no such checking for development endpoints. The only way you will know that the endpoint is borked is when you get the platform token error.
I sure hope this helps somebody out there, as it drove me to distraction.
I am using this. If the get endpoint response finds the NotFound error, it creates an endpoint (this should never happen, but hell, it's on AWS SNS documentation website).
If that doesn't happen, it means you're getting the info for the endpoint. It can either be ok (tokens match and enabled is true), or the other way around (in which case you need to update it).
- (void)getEndpointDetailsWithResponse:(void(^)(AWSSNSGetEndpointAttributesResponse *response, AWSTask *))handleResponse {
NSString * deviceTokenForAWS = [self deviceTokenForAWS];
AWSSNS *manager = [AWSSNS SNSForKey:#"EUWest1SNS"];
AWSSNSGetEndpointAttributesInput *input = [AWSSNSGetEndpointAttributesInput new];
input.endpointArn = self.endpointArn;
AWSTask *getEndpointAttributesTask = [manager getEndpointAttributes:input];
[getEndpointAttributesTask continueWithBlock:^id(AWSTask *task) {
NSLog(#"%# Error: %#", task.result, task.error);
AWSSNSGetEndpointAttributesResponse *result = task.result;
NSError *error = task.error;
if (error.code == AWSSNSErrorNotFound) {
[self createEndpointWithResponse:^(AWSSNSCreateEndpointResponse *createResponse) {
dispatch_async(dispatch_get_main_queue(), ^{
if (handleResponse != nil) {
handleResponse(result, task);
}
});
}];
} else {
NSLog(#"response for get endpoint attributes : %#", result);
NSString *token = [result.attributes valueForKey:#"Token"];
NSString *enabled = [result.attributes valueForKey:#"Enabled"];
NSLog(#"token : %#, enabled : %#", token, enabled);
BOOL wasSuccessful = [token isEqualToString:deviceTokenForAWS] && ([enabled localizedCaseInsensitiveCompare:#"true"] == NSOrderedSame);
if (!wasSuccessful) {
NSLog(#"device token does not match the AWS token OR it is disabled!");
NSLog(#"Need to update the endpoint");
AWSSNSSetEndpointAttributesInput *seai = [AWSSNSSetEndpointAttributesInput new];
seai.endpointArn = self.endpointArn;
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:deviceTokenForAWS, #"Token", #"true", #"Enabled", nil];
seai.attributes = attributes;
AWSTask *setEndpointAttributesTask = [manager setEndpointAttributes:seai];
[setEndpointAttributesTask continueWithBlock:^id(AWSTask *task) {
NSLog(#"response : %#, error: %#", task.result, task.error);
dispatch_async(dispatch_get_main_queue(), ^{
if (handleResponse != nil) {
handleResponse(result, task);
}
});
return nil;
}];
} else {
NSLog(#"all is good with the endpoint");
dispatch_async(dispatch_get_main_queue(), ^{
if (handleResponse != nil) {
handleResponse(result, task);
}
});
}
}
return nil;
}];
}
This is the exact replica of the AWS SNS token management documentation found here: https://mobile.awsblog.com/post/Tx223MJB0XKV9RU/Mobile-token-management-with-Amazon-SNS
I can attach the rest of my implementation if needed, but this part is the most important one.