Issue with getOrCreateAssociatedAccountInfo on Quicknode - solana-web3js

I just switched to Quicknode (testnet) as the public Solana node has IP limits. I notice that when I call token.getOrCreateAssociatedAccountInfo I encounter an issue which never happened on the main public node:
{"name":"Error","message":"Failed to find account","stack":"Error: Failed to find account\n at Token.getAccountInfo (/var/www/node_modules/#solana/spl-token/lib/index.cjs.js:493:13)\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n at async Token.getOrCreateAssociatedAccountInfo (/var/www/node_modules/#solana/spl-token/lib/index.cjs.js:338:16)\n at async SolanaBlockchainAPI.reward (/var/www/src/datasources/solanaBlockchain.js:266:35)
Is there some sort of compatibility issue ?
my code...
const token = new Token(
connection,
new web3.PublicKey(token_type.token_address),
TOKEN_PROGRAM_ID,
this.appTreasPair
);
const recipientTokenAddress = await token.getOrCreateAssociatedAccountInfo(
new web3.PublicKey(solana_public_address)
);

From the error it looks like there's some trouble locating the account that you're plugging into the getOrCreateAssociatedAccountInfo call.
There's not a lot of info to work with here, but my initial guess is you were working on the public solana devnet, and plugged into a testnet QuickNode URL, which would explain why the account isn't available for you.
Solution here would be to make sure you're on devnet instead of testnet when creating your QuickNode endpoint. Testnet really isn't used very much outside of people testing infrastructure. You're usually either working on production stuff (mainnet) or want to test out different functionalities on the developer testing net (devnet).

Related

Is there yet an idiomatic way to make native calls to AWS Lambda or API Gateway from a Flutter application?

Goal: Make a signed request (SigV4) to AWS Lambda or API Gateway from a Flutter application (iOS, for the sake of this question).
For context, AWS introduced support for "native calls to AWS backends in [...] Flutter or Dart applications" back in May of 2022. There is an example of how to sign a request to Cognito to gather information about a User Pool, but I have not seen any application of this concept for Lambda or API Gateway calls, yet.
I'm wondering if anyone else has had success using AWS's official Dart packages to send signed requests or knows of another way to securely call AWS from a Flutter application.
EDIT:
I was able to accomplish the goal. Here's how I did it:
The code (all-caps denotes placeholders for your own values):
import 'dart:convert';
import 'package:aws_common/aws_common.dart';
import 'package:aws_signature_v4/aws_signature_v4.dart';
const signer = AWSSigV4Signer(
credentialsProvider: AWSCredentialsProvider.dartEnvironment(),
);
const region = 'REGION';
Future<void> yourFunction() async {
final scope = AWSCredentialScope(
region: region,
service: AWSService.apiGatewayV2,
dateTime: AWSDateTime(DateTime.now()),
);
final request = AWSHttpRequest(
method: AWSHttpMethod.post,
uri: Uri.https('HOST.execute-api.REGION.amazonaws.com','/STAGE_NAME'),
headers: const {
AWSHeaders.contentType: 'application/x-amz-json-1.1',
},
body: json.encode({
'EVENT_KEY':'EVENT_VALUE',
}).codeUnits,
);
final signedRequest = await signer.sign(
request,
credentialScope: scope,
);
final resp = await signedRequest.send();
final respBody = await resp.decodeBody();
print('\n\n${signedRequest.headers}\n\n${respBody}\n\n${resp.statusCode}\n\n');
}
Within a single AWS region (except where n/a):
create IAM user with execute-api:Invoke permission and programmatic access; store keys securely for later use.
create a Lambda function (can be the default, for testing).
create API in API Gateway:
REST (not private)
Regional endpoint
Add method (for me, POST)
IAM authorization type
Integration type is Lambda
select the target Lambda function, but
do not use Lambda proxy
deploy the newly created API to a new stage (give it a name)
Edit your dart file to include the new resources, including the stage name.
Test your API within API Gateway (I was getting 502 until I unchecked "Lambda proxy integration").
Run the following in your terminal after a successful API test; be sure to insert the keys for the IAM user you created.
flutter run --dart-define=AWS_ACCESS_KEY_ID=... --dart-define=AWS_SECRET_ACCESS_KEY=...
Summary:
In my case, I have a button that executes this function. If you keep the print statement in the above dart code, you should hopefully see {"statusCode": 200, "body": "\"Hello from Lambda!\""} as the response body.
Hope this helps others. Cannot make any guarantees that my approach will work in another environment. I also may have forgotten to include something relevant in the steps above. Still open to questions and suggestions.
Thank you.

Web3 client can't write to contract in Flutter app using WalletConnect for credendtial

I used web3dart with flutter with Ganache and Truffle to run my Solidity contract, the contract is being read fine by my Flutter app but when I run functions that write to the contract it doesn't work (can't write to the contract from the app). I saw on the web3dart package it says you should use .sendTransaction() instead of .call() when running a function that writes to the contract
for the credential, I used WalletConnect I used the WalletConnectEthereumCredentials class that was written in the package example source code here
The transaction is successful from MetaMask wallet Address to the contract address(traceable with EtherScan), but still, contract data remains unchanged.
Solidity Code:
function update(string memory newMessage) public {
message = newMessage;
}
Flutter Code:
final cred = WalletConnectEthereumCredentials(provider: provider);
try {
var transactionId = await _web3client.sendTransaction(
cred,
Transaction.callContract(
contract: _deployedContract,
function: _updateFunction,
parameters: ["NEW_MESSAGE"],
from: EthereumAddress.fromHex(
cred.provider.connector.session.accounts[0]),
),
chainId: 4);
You can see what's on WalletConnectEthereumCredentials and WalletConnectEthereumCredentials on the walletConnect repository
Solved!
Just deploy the contract instead of running it locally on your machine.
I was basically trying to make a transaction to a contract that is running locally on Ganache. So I deployed the contract on truffle, this solved the issue and I can fully interact with the contract using my app.

Flutter call http requests from a unit\widget test without mocking

I have an app that follows MVC+service architecture. The service layer makes the http requests for rest APIs. However the response of the http requests change intermittently which cause my models to change or else random crashes in my app. SO to capture the change in these APIs I want to write some automated tests which can tell me exactly what changed. A sample test case is as following:
test("login_valid", () async {
final loginData = LoginData(
email: "abc#gmail.com",
password: "123"
);
final parameters = loginData.toJson();
var json = await httpService.post(parameters);
var loginResponse = LoginResponse.fromJson(json);
expect(loginResponse.status, "OK");
});
However, the above code throws SocketException upon run. I know this exception is thrown when INTERNET permission is not given in AndroidManifest.xml but I don't know how to set this for unit\widget tests.
P.S. I can't mock the service layer using mockit or similar framework because the whole point is to test my service layer which doesn't have any business logic but just provides network integration.
Any solution or suggestion will be really helpful. I am okay with other approaches to achieve the same intent also, if there are any.
Check this or the gihub issue discussion pointed there
https://timm.preetz.name/articles/http-request-flutter-test

issues deploying solidity smart contract to rinkeby test network

I'm using openZeppelin to make a crowdsale contract, all (30 of them) my tests pass with flying colours ;) and I can migrate on a locall ganache blockchain no problem.
When I try to deploy to rinkeby I start having issues. My config in truffle.js is
rinkeby: {
provider: rinkeybyProvider,
network_id: 3,
gas: 4712388,
gasPrice: web3.utils.toWei("40", "gwei"),
websockets: true,
from: "0x9793371e69ed67284a1xxxx"
}
When I deploy on rinkeby I get:
"SplitWallet" hit a require or revert statement somewhere in its
constructor. Try: * Verifying that your constructor params satisfy
all require conditions. * Adding reason strings to your require
statements.
I have gone through and put messages in every revert in the constructor hierachy, but I never see any of the messages. I thought it might be that my payees and shares were different lengths but, no, they are the same (only parameters that the constructor for a splitwallet take)
Things to note:
I have an infura api key
I am using truffle-wallet-provider provider, with just a private key (no mnemonic) to deploy
I am confused (due to the above), how my deploy script, can know multiple (10) wallets on deployment. Usually (in ganache) these are the 10 wallets ganache generates for you, but here, I am providing a private key, so it shouldn't be able to know 10 wallets, just one - the public key of the private key that is deploying the contract, no? (talking about here):
module.exports = async (
deployer,
network,
[owner, purchaser, investor, organisation, ...accounts] //how does it know these??
)
This last point, makes me wonder, because I printed out owner/purchaser and they dont match my public key wallet at all, so I have no idea where they are coming from. And if they dont match, and it defaults to the owner being accounts[0], then that wallet may not be able to pay for the gas.... perhaps??
Thanks
Rinkeby network id is 4, not 3.

Service Fabric ServicePartitionResolver ResolveAsync

I am currently using the ServicePartitionResolver to get the http endpoint of another application within my cluster.
var resolver = ServicePartitionResolver.GetDefault();
var partition = await resolver.ResolveAsync(serviceUri, partitionKey ?? ServicePartitionKey.Singleton, CancellationToken.None);
var endpoints = JObject.Parse(partition.GetEndpoint().Address)["Endpoints"];
return endpoints[endpointName].ToString().TrimEnd('/');
This works as expected, however if I redeploy my target application and its port changes on my local dev box, the source application still returns the old endpoint (which is now invalid). Is there a cache somewhere that I can clear? Or is this a bug?
Yes, they are cached. If you know that the partition is no longer valid, or if you receive an error, you can call the resolver.ResolveAsync() that has an overload that takes the earlier ResolvedServicePartition previousRsp, which triggers a refresh.
This api-overload is used in cases where the client knows that the
resolved service partition that it has is no longer valid.
See this article too.
Yes. They are cached. There are 2 solutions to overcome this.
The simplest code change that you need to do is replace var resolver = ServicePartitionResolver.GetDefault(); with var resolver = new ServicePartitionResolver();. This forces the service to create a new ServicePartitionResolver object to every time. Whereas, GetDefault() gets the cached object.
[Recommended] The right way of handling this is to implement a custom CommunicationClientFactory that implements CommunicationClientFactoryBase. And then initialize a ServicePartitionClient and call InvokeWithRetryAsync. It is documented clearly in Service Communication in the Communication clients and factories section.