Skip to content

Instantly share code, notes, and snippets.

Created July 8, 2022 10:59
Show Gist options
  • Save sevazhidkov/a674a5846fca111bd11ab42e30afa9bc to your computer and use it in GitHub Desktop.
Save sevazhidkov/a674a5846fca111bd11ab42e30afa9bc to your computer and use it in GitHub Desktop.
const axios = require('axios').default;
const { Keypair, PublicKey, Connection, Transaction, sendAndConfirmRawTransaction, LAMPORTS_PER_SOL } = require('@solana/web3.js');
const {
createMint, getOrCreateAssociatedTokenAccount, Account,
mintTo, createTransferInstruction, createAccount, getAccount, getAssociatedTokenAddress,
} = require('@solana/spl-token');
const base58 = require('bs58');
const baseURL = '';
async function main() {
const connection = new Connection('', 'confirmed');
// (1) Preparation
// Let's now connect to Octane instance and get some needed params:
// 1) how much we should pay for transaction in tokens
// 2) which account will pay for transaction in SOL (feePayer)
// Normally, you should also learn which kind of tokens supported and
// get price in each of them, but devnet endpoint accepts any token through
// config overrides.
const response = (await axios.get(baseURL, {
headers: {'Accept': 'application/json'}
const feePayer = new PublicKey(response.feePayer);
const mint = new PublicKey(response.endpoints.transfer.tokens[0].mint);
const feeAccount = new PublicKey(response.endpoints.transfer.tokens[0].account);
const simpleTransactionFee = response.endpoints.transfer.tokens[0].fee;
// (2) Prepare the hypothetical end user account
const endUserKeypair = Keypair.fromSecretKey(base58.decode(process.env.SECRET_KEY));
const endUserTokenAccount = await getAssociatedTokenAddress(mint, endUserKeypair.publicKey);
// (3) Create the transaction — we'll transfer some tokens to targetOwner as our first gasless transaction.
const targetOwner = new PublicKey('EmMC1F6X25qsnXVzNzKUyqFWfLF2GsVJW55fGJRm9feY');
const targetAccount = await getAssociatedTokenAddress(mint, targetOwner);
// The transaction would consist of two instructions:
// 1) token transfer to octane's token account as payment for running transaction gasless
// 2) the payload, actual instruction we want to execute. in this case, it's also a token transfer to targetKeypair, but it could be anything.
const transaction = new Transaction();
transaction.add(createTransferInstruction(endUserTokenAccount, feeAccount, endUserKeypair.publicKey, simpleTransactionFee));
transaction.add(createTransferInstruction(endUserTokenAccount, targetAccount, endUserKeypair.publicKey, 100));
transaction.feePayer = feePayer;
transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
transaction.partialSign(endUserKeypair); // in client code, you should use wallet adapter instead
// (4) Send the transaction to octane to sign and attach signature to transaction
const octaneResponse = (await + '/transfer', {
transaction: base58.encode(transaction.serialize({requireAllSignatures: false})),
transaction.addSignature(feePayer, base58.decode(octaneResponse.signature));
// (5) Send transaction to network
await sendAndConfirmRawTransaction(connection, transaction.serialize(), { commitment: 'confirmed' });
console.log('Find on mainnet explorer ///', octaneResponse.signature);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment