# Scale by Solana at Solana

**Dispersing SOL to 10,000 users in <120 seconds**\ <br>

import { Commitment, Keypair, LAMPORTS\_PER\_SOL, Signer, Transaction, } from "@solana/web3.js"; import { ConnectionManager, Disperse, TransactionBuilder, TransactionWrapper, Logger } from "@solworks/soltoolkit-sdk";

const COMMITMENT: Commitment = "confirmed"; const NO\_OF\_RECEIVERS = 10\_000; const CHUNK\_SIZE = 30; const TOTAL\_SOL = 10;

const SKIP\_AIRDROP = true; const SKIP\_SENDING = false; const SKIP\_BALANCE\_CHECK = true;

// generate keypair for example const sender = Keypair.fromSecretKey( Uint8Array.from(\[ 36, 50, 153, 146, 147, 239, 210, 72, 199, 68, 75, 220, 42, 139, 105, 61, 148, 117, 55, 75, 23, 144, 30, 206, 138, 255, 51, 206, 102, 239, 73, 28, 240, 73, 69, 190, 238, 27, 112, 36, 151, 255, 182, 64, 13, 173, 94, 115, 111, 45, 2, 154, 250, 93, 100, 44, 251, 111, 229, 34, 193, 249, 199, 238, ]) );

(async () => { const logger = new Logger("example");

// create connection manager const cm = await ConnectionManager.getInstance({ commitment: COMMITMENT, endpoints: \[ "<https://mango.devnet.rpcpool.com>",

```
  // https://docs.solana.com/cluster/rpc-endpoints
  // Maximum number of requests per 10 seconds per IP: 100 (10/s)
  // Maximum number of requests per 10 seconds per IP for a single RPC: 40 (4/s)
  // Maximum concurrent connections per IP: 40
  // Maximum connection rate per 10 seconds per IP: 40
  // Maximum amount of data per 30 second: 100 MB
  // "https://api.devnet.solana.com",

  // https://shdw.genesysgo.com/genesysgo/the-genesysgo-rpc-network
  // SendTransaction Limit: 10 RPS + 200 Burst
  // getProgramAccounts Limit: 15 RPS + 5 burst
  // Global Limit on the rest of the calls: 200 RPS
  "https://devnet.genesysgo.net",
],
mode: "round-robin",
network: "devnet",
```

});

if (!SKIP\_AIRDROP) { // airdrop 1 sol to new addresses, confirm and send sol to SENDER for (let i = 0; i < Math.ceil((TOTAL\_SOL + 1) / 1); i++) { // generate new keypair const keypair = Keypair.generate();

```
  // airdrop sol to the generated address
  const airdropSig = await cm
    .connSync({ airdrop: true })
    .requestAirdrop(keypair.publicKey, LAMPORTS_PER_SOL);
  logger.debug("Airdropped 1 SOL to", sender.publicKey.toBase58());

  // wait for confirmation
  logger.debug("Confirming airdrop transaction...");
  await TransactionWrapper.confirmTx({
    connectionManager: cm,
    changeConn: false,
    signature: airdropSig,
    commitment: "max",
    airdrop: true,
  });
  logger.debug("Airdrop transaction confirmed");

  // send sol to SENDER
  const tx = TransactionBuilder.create()
    .addSolTransferIx({
      from: keypair.publicKey,
      to: sender.publicKey,
      amountLamports: LAMPORTS_PER_SOL - 5000,
    })
    .build();

  const wrapper = await TransactionWrapper.create({
    connectionManager: cm,
    changeConn: false,
    signer: keypair.publicKey,
    transaction: tx,
  }).addBlockhashAndFeePayer(keypair.publicKey);
  const signedTx = await wrapper.sign({ signer: keypair as Signer });
  const sig = await wrapper.sendAndConfirm({
    serialisedTx: signedTx.serialize(),
    commitment: "max",
  });
  logger.debug(
    "Sent 1 SOL to",
    sender.publicKey.toBase58(),
    "with signature",
    sig
  );

  await sleep(1000);
}
```

}

// fetch balance of the generated address logger.debug("Fetching balance of", sender.publicKey.toBase58()); let senderBal = await cm // default value for changeConn = true .connSync({ changeConn: true }) .getBalance(sender.publicKey, COMMITMENT); logger.debug(`Sender balance: ${senderBal}`);

// generate receivers logger.debug(`Generating ${NO_OF_RECEIVERS} receivers...`); const receivers: Keypair\[] = \[]; for (let i = 0; i < NO\_OF\_RECEIVERS; i++) { receivers.push(Keypair.generate()); } logger.debug("Receivers generated");

// generate transactions const transfers: { amount: number; recipient: string; }\[] = \[];

const rentCost = (NO\_OF\_RECEIVERS+1) \* 5\_000; const transferAmount = Math.floor( (senderBal - rentCost) / NO\_OF\_RECEIVERS ); logger.debug(`Sending ${transferAmount} to ${NO_OF_RECEIVERS} receivers`); for (let i = 0; i < NO\_OF\_RECEIVERS; i++) { transfers.push({ amount: transferAmount, recipient: receivers\[i].publicKey.toBase58(), }); }

// send transactions if (!SKIP\_SENDING) { const transactions = await Disperse.create({ tokenType: "SOL", sender: sender.publicKey, transfers, }).generateTransactions();

```
const txChunks = chunk(transactions, CHUNK_SIZE);
for (let i = 0; i < txChunks.length; i++) {
  logger.debug(`Sending transactions ${i + 1}/${txChunks.length}`);
  const txChunk = txChunks[i];
  const conn = cm.connSync({ changeConn: true });

  await Promise.all(
    txChunk.map(async (tx: Transaction, i: number) => {
      logger.debug(`Sending transaction ${i + 1}`);

      // feed transaction into TransactionWrapper
      const wrapper = await TransactionWrapper.create({
        connection: conn,
        transaction: tx,
        signer: sender.publicKey,
      }).addBlockhashAndFeePayer(sender.publicKey);

      // sign the transaction
      logger.debug(`Signing transaction ${i + 1}`);
      const signedTx = await wrapper.sign({
        signer: sender as Signer,
      });

      // send and confirm the transaction
      logger.debug(`Sending transaction ${i + 1}`);
      const transferSig = await wrapper.sendAndConfirm({
        serialisedTx: signedTx.serialize(),
        commitment: COMMITMENT,
      });
      logger.debug("Transaction sent:", transferSig.toString());
    })
  );
  await sleep(1_000);
}
```

}

if (!SKIP\_BALANCE\_CHECK) { // fetch balance of the generated address logger.debug("Fetching balance of:", sender.publicKey.toBase58()); senderBal = await cm .connSync({ changeConn: true }) .getBalance(sender.publicKey, COMMITMENT); logger.debug(`Sender balance: ${senderBal}`);

```
// split addresses into chunks of CHUNK_SIZE
const chunks = chunk(receivers, CHUNK_SIZE);
const balances: {
  balance: number;
  address: string;
}[] = [];
for (let i = 0; i < chunks.length; i++) {
  const chunk = chunks[i];
  logger.debug(
    `Fetching balances for chunk ${i + 1} with ${chunk.length} addresses`
  );

  // cycle to new connection to avoid rate limiting
  let conn = cm.connSync({ changeConn: true });

  // fetch balances
  const results = await Promise.all(
    chunk.map(async (receiver: Keypair) => {
      const balance = await conn.getBalance(receiver.publicKey, COMMITMENT);
      logger.debug(
        `Balance of ${receiver.publicKey.toBase58()}: ${balance}`
      );
      return {
        balance,
        address: receiver.publicKey.toBase58(),
      };
    })
  );

  // add results to balances
  balances.push(...results);
  await sleep(1_000);
}

const totalBalance = balances.reduce((acc, curr) => acc + curr.balance, 0);
const numberWithNoBalance = balances.filter((b) => b.balance === 0).length;
const numberWithBalance = balances.filter((b) => b.balance > 0).length;
logger.debug(`Total amount sent: ${totalBalance}`);
logger.debug(`Number of addresses with no balance: ${numberWithNoBalance}`);
logger.debug(`Number of addresses with balance: ${numberWithBalance}`);
```

} })();

function chunk(arr: any\[], len: number) { var chunks: any\[] = \[], i = 0, n = arr.length;

while (i < n) { chunks.push(arr.slice(i, (i += len))); } return chunks; }

function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); }


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sevenheaven.gitbook.io/sevenheaven/tokenization/scale-by-solana-at-solana.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
