Would appreciate guidance on how to obtain the data back in the variables, which was entered into splToken.createTransferInstruction(), step-by-step, from the buffer variable in the code snippet below:
var transaction = new web3.Transaction();
transaction.add(
splToken.createTransferInstruction(
fromTokenAccount,
toTokenAccount,
senderPublicKey,
amount,
[],
splToken.TOKEN_PROGRAM_ID,
)
);
// Setting the variables for the transaction
transaction.feePayer = provider.publicKey;
let blockhashObj = await connection.getRecentBlockhash();
transaction.recentBlockhash = await blockhashObj.blockhash;
// Transaction constructor initialized successfully
if(transaction) { console.log('Txn created successfully'); }
// Request creator to sign the transaction (allow the transaction)
let signed = await provider.signTransaction(transaction);
let buffer = signed.serialize();
Using web3.Transaction.from(buffer) I obtained a Transaction object - see image from the browser's console:
I need to do something with instructions[0].data, I suppose to break it into byte lengths that will allow me to repopulate from the signed transaction:
fromTokenAccount,
toTokenAccount,
senderPublicKey,
amount,
[], // would this be a variable or zero-byte?
splToken.TOKEN_PROGRAM_ID,
from the splToken.createTransferInstruction() above.
Much appreciated!
From the TransactionInstruction, you can use decodeTransferInstruction to get back the initial parameters. In your case, you can call:
let tx = web3.Transaction.from(buffer);
let decodedIx = decodeTransferInstruction(tx.instructions[0]);
console.log(decodedIx.keys.source);
console.log(decodedIx.keys.destination);
console.log(decodedIx.keys.owner);
console.log(decodedIx.data.amount);
Full source code available at: https://github.com/solana-labs/solana-program-library/blob/24baf875e9e19c26d694d28c557d33848c3a9180/token/js/src/instructions/transfer.ts#L87
Related
How can I get a gasFee estimate for a transaction of my custom contract?
For a normal transaction execution from the SPL library I can do so like this:
import { Transaction } from '#solana/web3.js';
const transaction = new Transaction({
recentBlockhash: recentBlockhash.blockhash,
feePayer: wallet.publicKey
}).add(
// someFunctionCall
);
const estimatedGas = await transaction.getEstimatedFee(connection);
But I do not use new Transaction() to call my custom Program's methods. It's done like:
const tx = await program.methods
.myCustomMethod(...)
.accounts(...)
.rpc();
How can I estimate the gas for the tx w/o actually calling it?
A demo example to print estimated gas cost for transaction created usign Anchor:
const txn = await program.methods
.exchange10(sBump, BNF(exchangeBal1))
.accounts({
feeRecipient: feeRecipient.publicKey,
seller: sellerPDA,
sellerTokenAccount: sellerTknAcc.address,
buyer: wallet2.publicKey,
buyerTokenAccount: buyerTknAcc.address,
tokensForSale: tokensForSalePDA,
tokenProgram: TOKEN_PROGRAM_ID,
})
.signers([wallet2])
.transaction();
txn.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
txn.feePayer = wallet2.publicKey;
console.log(await txn.getEstimatedFee(connection))
I found out you can replace .rpc() with .transaction() which will return an object of type Transaction (from #solana/web3.js).
Then you can exercise the same logic for gas estimation on that object as in the first example.
And, of course, you will need to sendAndConfirm the transaction as an extra step, because otherwise the .rpc() call was taking care of that.
So I programmed a system that saves the ids of certain channels (plus messages) and saves them in a file. After restarting the bot, the IDs will be read and reused. For example, fetching the specific message to edit it, therefore. Unfortunately, the cache is undefined, empty or an error occurs. Could somebody show me how to fetch a message which isn't in the cache?
Example code for an existing message and channel:
const {Discord, Client, Intents, Permissions, MessageEmbed} = require('discord.js');
const bot = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MEMBERS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_MESSAGE_REACTIONS, Intents.FLAGS.GUILD_MESSAGE_TYPING, Intents.FLAGS.GUILD_PRESENCES, Intents.FLAGS.DIRECT_MESSAGES, Intents.FLAGS.DIRECT_MESSAGE_REACTIONS, Intents.FLAGS.DIRECT_MESSAGE_TYPING, Intents.FLAGS.GUILD_VOICE_STATES]});
bot.channels.cache.get('597102497420673025').messages.cache.get('959413368911966251').embeds;
Error:
var test = bot.channels.cache.get('597102497420673025').messages.cache.get('959413368911966251').embeds;
^
TypeError: Cannot read properties of undefined (reading 'embeds')
at Client.<anonymous> (D:\E-verysBot\index.js:2288:99)
at Client.emit (node:events:402:35)
at WebSocketManager.triggerClientReady (D:\E-verysBot\node_modules\discord.js\src\client\websocket\WebSocketManager.js:384:17)
at WebSocketManager.checkShardsReady (D:\E-verysBot\node_modules\discord.js\src\client\websocket\WebSocketManager.js:367:10)
at WebSocketShard.<anonymous> (D:\E-verysBot\node_modules\discord.js\src\client\websocket\WebSocketManager.js:189:14)
at WebSocketShard.emit (node:events:390:28)
at WebSocketShard.checkReady (D:\E-verysBot\node_modules\discord.js\src\client\websocket\WebSocketShard.js:475:12)
at WebSocketShard.onPacket (D:\E-verysBot\node_modules\discord.js\src\client\websocket\WebSocketShard.js:447:16)
at WebSocketShard.onMessage (D:\E-verysBot\node_modules\discord.js\src\client\websocket\WebSocketShard.js:301:10)
at WebSocket.onMessage (D:\E-verysBot\node_modules\ws\lib\event-target.js:199:18)
Node.js v17.3.0
You fetch a message, to cache it.
// asynchronously
const channel = client.channels.cache.get(`channelId`);
const message = await channel.messages.fetch(`messageId`);
return message.embeds;
// synchronously
const channel = client.channels.cache.get(`channelId`);
channel.messages.fetch(`messageId`).then(message => {
return message.embeds;
})
I hope this fixes your problem!
After I create my own token program I am thne minting some supply into another tokenaccount.
I notice the mintTo is a void function, is there any easy way to get the associated transaction signature ?
const token = new splToken.Token(
connection,
new web3.PublicKey(token_type.token_address),
splToken.TOKEN_PROGRAM_ID,
mint_authority_wallet
);
const destinationTokenAccount = await token.getOrCreateAssociatedAccountInfo(
new web3.PublicKey(to_public_address)
);
console.log("destinationTokenAccount>>", destinationTokenAccount);
const test = await token.mintTo(
destinationTokenAccount.address,
mint_authority_wallet.publicKey,
[],
100
);
console.log("test>>",test)
The fix for this is quite simple: you just need to return the result from sendAndConfirmTransaction. Check out the source code at https://github.com/solana-labs/solana-program-library/blob/ab05e4e597c0b538d855c18da3850df84ad6a49a/token/js/client/token.js#L1027
You could always hack your version to return the signature. Better yet, PRs are always welcome!
When calling a contract method with attached deposits, you are redirected to the NEAR wallet for approving the transaction. How can the contract frontend app get the result of the transaction after returning from the wallet?
I've faced the same problem. For this moment near-api set transaction info in the browser url. So you get the transaction hash from url after returning from the wallet. Then using transaction hash get info about it using near-api-js:
const { providers } = require("near-api-js");
//network config (replace testnet with mainnet or betanet)
const provider = new providers.JsonRpcProvider(
"https://archival-rpc.testnet.near.org"
);
const TX_HASH = "9av2U6cova7LZPA9NPij6CTUrpBbgPG6LKVkyhcCqtk3";
// account ID associated with the transaction
const ACCOUNT_ID = "sender.testnet";
getState(TX_HASH, ACCOUNT_ID);
async function getState(txHash, accountId) {
const result = await provider.txStatus(txHash, accountId);
console.log("Result: ", result);
}
Documentation: https://docs.near.org/docs/api/naj-cookbook#get-transaction-status
There are 2 options:
Use provider.txStatus like Tom Links said. But the cons : we only know transaction success or fail but not the response from smart contract.
Seperate deposit api and actions api -> User must deposit before call actions api, so we can read the response.
With v5 PublishRequest extension was removed from the IBus interface.
We used the callback to handle multiple response types that could be returned from the consumer ( Faults, Validations, actual responses, etc )
What is the equivalent way of publishing a message and wiring up multiple response types ?
// Request/Response contracts, may also return validation failure or fault contract
Request<TMessage> request = await bus.PublishRequest<TMessage>( msg, context => {
context.Handle<TResponse>( value => ... );
context.Handle<TValidation>( value => ... );
context.Handle<Fault>( value => ... );
context.CorrelationId = ...
context.Headers.Set( ... );
});
await request.Task;
You can use the new syntax, which is much cleaner overall.
var client = Bus.CreateRequestClient<RegisterMember>();
var (registered, existing) =
await client.GetResponse<MemberRegistered, ExistingMemberFound>(
new RegisterMember() {MemberId = "Johnny5"});
This will return either of the two responses, and if a fault occurs, either will throw the faulted request exception.
You can also use a request handle to add headers, etc.
var client = Bus.CreateRequestClient<RegisterMember>();
var request = client.Create(new RegisterMember()
{MemberId = "Johnny5"});
// the request is also the send pipe configurator, so...
request.UseExecute(context => context.CorrelationId = someId);
var (registered, existing) =
await request.GetResponse<MemberRegistered, ExistingMemberFound>();
You can see a working test case in the future tests:
https://github.com/MassTransit/MassTransit/blob/develop/src/MassTransit.Futures.Tests/Request_Specs.cs#L170