connect to localhost using solana web3.js - solana

I'm building a miniature next react app (for test purpose) to test a js script that i made, that is supposed to mint NFT on my account. I'm following this to makes everything works.
But, when i try any of these two:
const connection = new Connection(
clusterApiUrl('devnet'),
);
const connection = new Connection(
"http://127.0.0.1:8899",
);
then i get an error in createMint function:
let mint = await createMint(
connection,
mintRequester, // payer
mintRequester.publicKey, // mint
null, // freeze
0,
);
the error is:
Unhandled Runtime Error
TypeError: unexpected type, use Uint8Array
Source
scripts/mint.ts (48:4) # async*_callee$
46 |
47 | let mint = await createMint(
> 48 | connection,
| ^
49 | mintRequester, // payer
50 | mintRequester.publicKey, // mint
51 | null, // freeze
note: testnet timeout, cant use it

Related

How to create token for unit test on Solana

I'm trying to create token/nft for testing my transfer method in unit test.
Here is my code:
const connection = new Connection("https://api.devnet.solana.com");
const myKeypair = web3.Keypair.generate();
const fromAirdropSignature = await connection.requestAirdrop(myKeypair.publicKey, 2 * anchor.web3.LAMPORTS_PER_SOL);
await connection.confirmTransaction(fromAirdropSignature);
let minter = await splToken.createMint(connection, myKeypair, myKeypair.publicKey, null, 1, web3.Keypair.generate(), null, splToken.TOKEN_PROGRAM_ID)
I tried this way but when I run anchor test, sometimes requestAirdrop doesn't work. Is this the right way to do? How can I fix this?
When using devnet, you will always be limited in how much you can airdrop. You can get around that by doing one airdrop and reusing the same myKeypair for all of your test runs.
The best environment for unit tests, however, is a local solana-test-validator, which has higher limits for airdrops, and can be destroyed / recreated anytime.
Before running your tests, in a separate shell, you can run:
$ solana-test-validator -r
And then connect to it using:
const connection = new Connection("http://localhost:8899");

How do I force Solana/Anchor methods to use the devnet?

In creating a simple program, I can't get Solana to use the devnet for its RPC connection. I keep getting the following error:
{
blockhash: '7TTVjRKApwAqP1SA7vZ2tQHuh6QbnToSmVUA9kc7amEY',
lastValidBlockHeight: 129662699
}
Error: failed to get recent blockhash: FetchError: request to http://localhost:8899/ failed, reason: connect ECONNREFUSED 127.0.0.1:8899
at Connection.getRecentBlockhash (/home/simeon/dev/freelance/niels_vacancies/node_modules/#solana/web3.js/lib/index.cjs.js:6584:13)
even though I have set all of my settable constants like ANCHOR_PROVIDER_URL=https://api.devnet.solana.com, or the relevant entries in my Anchor.toml file. I also explicitly specify the following:
const connection = new anchor.web3.Connection("https://api.devnet.solana.com/", {commitment: "max"});
const wallet = anchor.Wallet.local();
const provider = new anchor.Provider(
connection,
wallet,
{
commitment: "max",
preflightCommitment: "max",
skipPreflight: false
}
)
I even test console.log(await anchor.getProvider().connection.getLatestBlockhash()); to ensure that I can, in fact, get a blockhash from the devnet. What can I do to force the RPC calls to do so too?
You just have to set the Anchor.toml cluster to devnet and programs.devnet and then deploy the program using a wallet with devnet-sol. I will drop an Anchor.toml for devnet.
[features]
seeds = false
[programs.devnet]
first_program = "FPT...bd3"
[registry]
url = "https://anchor.projectserum.com"
[provider]
cluster = "devnet"
wallet = "PATH/TO/WALLET/WHO/WILL/PAY/FOR/DEPLOY.json"
[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
in this case the first_program is the program_id declared on the declare_id macro.
Then you can use ur test file totally normal with anchor.setProvider(anchor.Provider.env());
If you have already updated the anchor.toml to use devnet, and are having this issue with program.provider.connection.whatever or program.account.whatever.fetch.whatever, make sure that you have set the anchor provider BEFORE creating the program, e.g:
const provider = AnchorProvider.env();
anchor.setProvider(provider);
must come before the line
const program: Program<Whatever> = workspace.Whatever;

How to make a bot respond to a certain message sent after the command?

I am trying to make a bot that simulates a turn based battle, but i have no idea how to make a bot respond after i've sent the command. what i have tried for now is:
async def battle(ctx):
keyword = (1,2,3)
enemy1 = ('Skeleton', 'Goblin', 'Bandit',)
enemy2 = ('Knight', 'Barbarian', 'Archer')
enemy3 = ('Elf Mage', 'Dwarf Warrior', 'Orc Brute')
enemy1hp = 50
enemy1dmg = 25
enemy2hp = 75
enemy2dmg = 35
enemy3hp = 100
enemy3dmg = 25
playerhp = 150
playerdmg = random.randint(10, 40)
await ctx.send('Pick a number between 1 and 3')
enemypicked = ctx.content.lower()
for keyword in enemypicked:
if keyword == '1':
opponent1 = random.choice(enemy1)
await ctx.send(f'{opponent1}, {enemy1hp}HP')
What i am trying to do is make the user choose a number and dependant on a number the bot will choose which enemy will appear,but i get the following error:
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'Context' object has no attribute 'content'
and i am out of ideas on how to make it work. Any help is highly appreciated.
To fix your Exception, look into ctx.message.
You can then use ctx.message.content to get the content of the message.
Then to wait_for a response, look into https://discordpy.readthedocs.io/en/latest/ext/commands/api.html?highlight=wait_for#discord.ext.commands.Bot.wait_for

Why does the first response takes more time in GAS web app?

Edit: I am using clasp. Updated the code to the actual GAS!
I have a GAS deployed as a web app. We send POST requests from Slack via a slash command and it needs a response in less than 3000ms because GAS can't handle asynchronous code.
At the first request, it takes more than 3000ms to send a response but on the following requests, it is around 1500ms.
The doPost function looks like the following.
var exports = exports || {};
var module = module || { exports: exports };
Logger = BetterLog.useSpreadsheet('spreadsheetId');
function doPost(request) {
var startExecutionDate = new Date();
var path = request.parameter.path;
Logger.log("Request received with path: " + path);
var response = Responses.Error;
var token = request.parameter.token;
if (path.startsWith('/slack')) {
Logger.log("Slack request");
var slackRouter = new SlackRouter();
response = slackRouter.post(request);
// ...
}
// ...
}
And this is the code for the Slack Router.
var exports = exports || {};
var module = module || { exports: exports };
var SlackRouter = (function () {
function SlackRouter() {
}
SlackRouter.prototype.post = function (request) {
var path = request.parameter.path;
switch (path) {
case Routes.Team:
Logger.log("For team");
// ...
}
};
return SlackRouter;
}());
exports.SlackRouter = SlackRouter;
I have the timestamps for each log.
First attempt
| Timestamp | Delta in ms | Log Message |
|--------------|-------------|---------------|
| 11:22:34:164 | 0 | Path: ... |
| 11:22:35:354 | 1190 | Slack request |
| 11:22:35:462 | 108 | For team |
Second attempt
| Timestamp | Delta in ms | Log Message |
|--------------|-------------|---------------|
| 11:22:45:047 | 0 | Path: ... |
| 11:22:45:164 | 117 | Slack request |
| 11:22:45:350 | 186 | For team |
I had several ideas already like the web app goes to a sleep state but since we calculate delta from the first log message it doesn't make sense.
So what is going on behind the scenes? Are you aware of any easy workarounds? If possible I don't want to build a microservice to send a response to Slack in time and later send the actual response.
The Apps Script servers don't keep every script ever written or deployed loaded in memory, and so scripts that haven't been run in a while need to be loaded from disk first. This is usually referred to as a "cold start time" in Cloud providers.
Answered by Eric Koleda on Google Apps Script Community forum
The most glaring issue is your use of ES6 syntax in your doPost() method.
Google Apps Script does not support ES6 template string syntax and only partially supports destructuring assignments. So that might be your issue. Your doPost() probably fails to return a value as a result so Slack likely repeats the request until it times out.
Try removing the BetterLog library. That may be causing the initial first-time delay.
https://developers.google.com/apps-script/guides/libraries
Warning: A script that uses a library does not run as quickly as it would if all the code were contained within a single script project. Although libraries can make development and maintenance more convenient, you should use them sparingly in projects where speed is critical. Because of this issue, library use should be limited in add-ons.

InitializeSecurityContext (Schannel) returns SEC_I_INCOMPLETE_CREDENTIALS unexpectedly

I have implemented a code for creating a secure connection using SSPI. I use it for sending mail over SMTP. It works fine with smtp.gmail.com and some other servers which I tried it with. But it doesn't work with smtp.live.com. The second call of InitializeSecurityContext() returns me SEC_I_INCOMPLETE_CREDENTIALS. As I understand this means that I need to provide a client certificate. But this is a public free mail server. What client certificate can it require?? Or maybe I use some wrong parameters or flags?
I connect to smtp.live.com:587 Initially the connection is unencrypted, plain text. First, I send EHLO command, then I send STARTTLS command. After that I perform an SSL handshake using the code below
Here is the code :
SCHANNEL_CRED schCred;
memset(&schCred,0,sizeof(schCred));
schCred.dwVersion=SCHANNEL_CRED_VERSION; // == 4
schCred.dwFlags=SCH_CRED_NO_DEFAULT_CREDS;
// acquire credentials
SECURITY_STATUS status=
AcquireCredentialsHandle(NULL,UNISP_NAME,SECPKG_CRED_OUTBOUND,NULL,
&schCred,NULL,NULL,&Creds,NULL);
// then I create a context
const DWORD dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT |
ISC_REQ_REPLAY_DETECT |
ISC_REQ_CONFIDENTIALITY |
ISC_RET_EXTENDED_ERROR |
ISC_REQ_ALLOCATE_MEMORY |
ISC_REQ_STREAM;
SECURITY_STATUS scRet =
InitializeSecurityContextW(&Creds, NULL, targetName, dwSSPIFlags,
0, 0 , NULL, 0, &Context,&outBuffer, &dwSSPIOutFlags, &tsExpiry);
// scRet==SEC_I_CONTINUE_NEEDED
SendOutBuffer(outBuffers);
ReceiveInputBuffers(inBuffers);
// Then I call InitializeSecurityContext for the second time
scRet = InitializeSecurityContext(&Creds, &Context, NULL, dwSSPIFlags,
0, 0, &inBuffer, 0, NULL, &outBuffer, &dwSSPIOutFlags, &tsExpiry);
if( ( SEC_E_OK == scRet || SEC_I_CONTINUE_NEEDED == scRet ||
FAILED(scRet) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR) )
&& BufferNotEmpty(outBuffers)) {
SendOutBuffer(outBuffers);
}
if(SEC_I_INCOMPLETE_CREDENTIALS == scRet) {
// This is where I am when connecting to smtp.live.com
}
Answering my own question. I captured traffic with Wireshark and yes, smtp.live.com does ask for a client certificate during a TLS handshake. But it's enough to send it an empty (zero length) certificate to proceed with the handshake. To do so, right after getting SEC_I_INCOMPLETE_CREDENTIALS, I just call InitializeSecurityContext() again with the same parameters. In other words, after getting SEC_I_INCOMPLETE_CREDENTIALS, I continue the handshake loop but skip the receiving of the input buffers for the next one itteration. If I'm getting SEC_I_INCOMPLETE_CREDENTIALS for a second time, I quit with an error because my client does not support authentication with a certificate. (Actually, I'm not sure if it's possible to get SEC_I_INCOMPLETE_CREDENTIALS twice)

Resources