Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Solana support #122

Merged
merged 13 commits into from
Mar 19, 2024
Merged

Adding Solana support #122

merged 13 commits into from
Mar 19, 2024

Conversation

johnpmitsch
Copy link
Contributor

@johnpmitsch johnpmitsch commented Mar 14, 2024

import { solanaWeb3, Solana } from "@quicknode/sdk";
const { Transaction, SystemProgram, Keypair, PublicKey } = solanaWeb3;

const mainSecretKey = Uint8Array.from([
//redacted
]);
const sender = Keypair.fromSecretKey(mainSecretKey);
const receiver = new PublicKey("redacted");
const senderPublicKey = sender.publicKey;

const endpoint = new Solana({
  endpointUrl:
    "https://some-cool-name.solana-mainnet.quiknode.pro/redacted",
});

const transaction = new Transaction();

// Add instructions for each receiver
transaction.add(
  SystemProgram.transfer({
    fromPubkey: senderPublicKey,
    toPubkey: receiver,
    lamports: 10,
  })
);

(async () => {
  // can use endpoint.connection, is @solana/web3js Connection
  // await endpoint.connection.sendTransaction(...)

  // Endpoint must added to Priority Fee API to do this
  const signature = await endpoint.sendSmartTransaction({
    transaction,
    keyPair: sender,
    feeLevel: "high"
  });
  console.log(signature);
})().catch(console.error);

If the user doesn't have the add-on installed:

image

@coveralls
Copy link

coveralls commented Mar 14, 2024

Coverage Status

coverage: 95.714% (-3.0%) from 98.726%
when pulling 94ff395 on solana
into 7150e52 on main.

Comment on lines 28 to 43
async sendWithPriorityFees(
transaction: Transaction,
keyPair: Keypair,
feeLevel: PriorityFeeLevels = 'medium'
) {
// eslint-disable-next-line prefer-const
let [computeUnitPriceInstruction, units, recentBlockhash] =
await Promise.all([
this.createDynamicPriorityFeeInstruction(feeLevel),
this.getSimulationUnits(
this.connection,
transaction.instructions,
keyPair.publicKey
),
this.connection.getLatestBlockhash(),
]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the issue is that your simulation did not include the priority fee instruction…so it’s returning too few compute units. If you fetch the priority fee before the simulation and pass it into your simulation transaction it works:

Suggested change
async sendWithPriorityFees(
transaction: Transaction,
keyPair: Keypair,
feeLevel: PriorityFeeLevels = 'medium'
) {
// eslint-disable-next-line prefer-const
let [computeUnitPriceInstruction, units, recentBlockhash] =
await Promise.all([
this.createDynamicPriorityFeeInstruction(feeLevel),
this.getSimulationUnits(
this.connection,
transaction.instructions,
keyPair.publicKey
),
this.connection.getLatestBlockhash(),
]);
async sendWithPriorityFees(
transaction: Transaction,
keyPair: Keypair,
feeLevel: PriorityFeeLevels = 'medium'
) {
const computeUnitPriceInstruction = await this.createDynamicPriorityFeeInstruction(feeLevel);
const allInstructions = [...transaction.instructions, computeUnitPriceInstruction];
// eslint-disable-next-line prefer-const
let [units, recentBlockhash] =
await Promise.all([
this.getSimulationUnits(
this.connection,
allInstructions,
keyPair.publicKey
),
this.connection.getLatestBlockhash(),
]);

@johnpmitsch johnpmitsch marked this pull request as ready for review March 17, 2024 23:44
if (units) {
units = Math.ceil(units * 1.05); // margin of error
transaction.add(ComputeBudgetProgram.setComputeUnitLimit({ units }));
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@johnpmitsch I'm wondering if insteading of (or maybe in addition) this being a sendSmartTransaction it's assembleSmartTransaction (or something like that), where we return the new Transaction object instead of sending it to the network.
the benefit here is that many circumstances, you're dealing w/ a wallet, not a keypair. In that case, I think it might be more useful to be able to pass in my instructions (or transaction) and return the smart transaction...then I can sign/send with my wallet adapter.
WDYT?

} from './types';

export class Solana {
readonly endpointUrl: string;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason this shouldn't be private?

Comment on lines +147 to +149
const computeUnitPriceInstruction =
await this.createDynamicPriorityFeeInstruction(feeLevel);
const testInstructions = [...instructions, computeUnitPriceInstruction];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you don't need this since you pass allInstructionsn

Suggested change
const computeUnitPriceInstruction =
await this.createDynamicPriorityFeeInstruction(feeLevel);
const testInstructions = [...instructions, computeUnitPriceInstruction];
const testInstructions = instructions, computeUnitPriceInstruction;

*/
async prepareSmartTransaction(args: PrepareSmartTransactionArgs) {
const { transaction, payerPublicKey, feeLevel = 'medium' } = args;
const computeUnitPriceInstruction =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there any risk that these values go stale while we process the rest of the function?

@johnpmitsch johnpmitsch merged commit a64bff0 into main Mar 19, 2024
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants