Просмотр исходного кода

ts: Batch calls to getMultipleAccounts (#763)

Dana Hanna 4 лет назад
Родитель
Сommit
fe355ed159
2 измененных файлов с 34 добавлено и 0 удалено
  1. 14 0
      ts/src/utils/common.ts
  2. 20 0
      ts/src/utils/rpc.ts

+ 14 - 0
ts/src/utils/common.ts

@@ -4,3 +4,17 @@
  */
 export const isBrowser =
   typeof window !== "undefined" && !window.process?.hasOwnProperty("type");
+
+/**
+ * Splits an array into chunks
+ *
+ * @param array Array of objects to chunk.
+ * @param size The max size of a chunk.
+ * @returns A two dimensional array where each T[] length is < the provided size.
+ */
+export function chunks<T>(array: T[], size: number): T[][] {
+  return Array.apply(
+    0,
+    new Array(Math.ceil(array.length / size))
+  ).map((_, index) => array.slice(index * size, (index + 1) * size));
+}

+ 20 - 0
ts/src/utils/rpc.ts

@@ -8,6 +8,7 @@ import {
   Transaction,
   TransactionInstruction,
 } from "@solana/web3.js";
+import { chunks } from "../utils/common";
 import { Address, translateAddress } from "../program/common";
 import Provider, { getProvider } from "../provider";
 
@@ -38,11 +39,30 @@ export async function invoke(
   return await provider.send(tx);
 }
 
+const GET_MULTIPLE_ACCOUNTS_LIMIT: number = 99;
+
 export async function getMultipleAccounts(
   connection: Connection,
   publicKeys: PublicKey[]
 ): Promise<
   Array<null | { publicKey: PublicKey; account: AccountInfo<Buffer> }>
+> {
+  if (publicKeys.length <= GET_MULTIPLE_ACCOUNTS_LIMIT) {
+    return await getMultipleAccountsCore(connection, publicKeys);
+  } else {
+    const batches = chunks(publicKeys, GET_MULTIPLE_ACCOUNTS_LIMIT);
+    const results = await Promise.all<
+      Array<null | { publicKey: PublicKey; account: AccountInfo<Buffer> }>
+    >(batches.map((batch) => getMultipleAccountsCore(connection, batch)));
+    return results.flat();
+  }
+}
+
+async function getMultipleAccountsCore(
+  connection: Connection,
+  publicKeys: PublicKey[]
+): Promise<
+  Array<null | { publicKey: PublicKey; account: AccountInfo<Buffer> }>
 > {
   const args = [publicKeys.map((k) => k.toBase58()), { commitment: "recent" }];
   // @ts-ignore