forked from raydium-io/raydium-sdk-V2
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
1,489 additions
and
526 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import { AccountInfo, Commitment, Connection, PublicKey } from "@solana/web3.js"; | ||
|
||
import { chunkArray } from "./lodash"; | ||
import { createLogger } from "./logger"; | ||
|
||
interface MultipleAccountsJsonRpcResponse { | ||
jsonrpc: string; | ||
id: string; | ||
error?: { | ||
code: number; | ||
message: string; | ||
}; | ||
result: { | ||
context: { slot: number }; | ||
value: { data: Array<string>; executable: boolean; lamports: number; owner: string; rentEpoch: number }[]; | ||
}; | ||
} | ||
|
||
export interface GetMultipleAccountsInfoConfig { | ||
batchRequest?: boolean; | ||
commitment?: Commitment; | ||
} | ||
|
||
const logger = createLogger("Raydium.accountInfo.util"); | ||
|
||
export async function getMultipleAccountsInfo( | ||
connection: Connection, | ||
publicKeys: PublicKey[], | ||
config?: GetMultipleAccountsInfoConfig, | ||
): Promise<(AccountInfo<Buffer> | null)[]> { | ||
const { batchRequest, commitment } = { | ||
batchRequest: false, | ||
...config, | ||
}; | ||
|
||
const chunkedKeys = chunkArray(publicKeys, 100); | ||
let results: (AccountInfo<Buffer> | null)[][] = new Array(chunkedKeys.length).fill([]); | ||
|
||
if (batchRequest) { | ||
const batch = chunkedKeys.map((keys) => { | ||
const args = connection._buildArgs([keys.map((key) => key.toBase58())], commitment, "base64"); | ||
return { | ||
methodName: "getMultipleAccounts", | ||
args, | ||
}; | ||
}); | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore | ||
const unsafeResponse: MultipleAccountsJsonRpcResponse[] = await connection._rpcBatchRequest(batch); | ||
results = unsafeResponse.map((unsafeRes: MultipleAccountsJsonRpcResponse) => { | ||
if (unsafeRes.error) { | ||
logger.error(`failed to get info for multiple accounts, RPC_ERROR, ${unsafeRes.error.message}`); | ||
throw new Error("failed to get info for multiple accounts"); | ||
} | ||
|
||
return unsafeRes.result.value.map((accountInfo) => { | ||
if (accountInfo) { | ||
const { data, executable, lamports, owner, rentEpoch } = accountInfo; | ||
|
||
if (data.length !== 2 && data[1] !== "base64") { | ||
logger.error(`info must be base64 encoded, RPC_ERROR`); | ||
throw new Error("info must be base64 encoded"); | ||
} | ||
|
||
return { | ||
data: Buffer.from(data[0], "base64"), | ||
executable, | ||
lamports, | ||
owner: new PublicKey(owner), | ||
rentEpoch, | ||
}; | ||
} | ||
return null; | ||
}); | ||
}); | ||
} else { | ||
try { | ||
results = (await Promise.all( | ||
chunkedKeys.map((keys) => connection.getMultipleAccountsInfo(keys, commitment)), | ||
)) as (AccountInfo<Buffer> | null)[][]; | ||
} catch (error) { | ||
if (error instanceof Error) { | ||
logger.error(`failed to get info for multiple accounts, RPC_ERROR, ${error.message}`); | ||
throw new Error("failed to get info for multiple accounts"); | ||
} | ||
} | ||
} | ||
|
||
return results.flat(); | ||
} | ||
|
||
export async function getMultipleAccountsInfoWithCustomFlags<T extends { pubkey: PublicKey }>( | ||
connection: Connection, | ||
publicKeysWithCustomFlag: T[], | ||
config?: GetMultipleAccountsInfoConfig, | ||
): Promise<({ accountInfo: AccountInfo<Buffer> | null } & T)[]> { | ||
const multipleAccountsInfo = await getMultipleAccountsInfo( | ||
connection, | ||
publicKeysWithCustomFlag.map((o) => o.pubkey), | ||
config, | ||
); | ||
|
||
return publicKeysWithCustomFlag.map((o, idx) => ({ ...o, accountInfo: multipleAccountsInfo[idx] })); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** | ||
* https://youmightnotneed.com/lodash/ | ||
*/ | ||
|
||
export function chunkArray<T>(arr: T[], chunkSize = 1, cache: T[][] = []): T[][] { | ||
const tmp = [...arr]; | ||
if (chunkSize <= 0) return cache; | ||
while (tmp.length) cache.push(tmp.splice(0, chunkSize)); | ||
return cache; | ||
} | ||
|
||
export function intersection<T>(arr: T[], ...args: T[][]): T[] { | ||
return arr.filter((item) => args.every((arr) => arr.includes(item))); | ||
} | ||
|
||
export function xor<T>(arr: T[], ...args: T[][]): T[] { | ||
return arr.filter((item) => args.every((arr) => !arr.includes(item))); | ||
} | ||
|
||
export function uniq<T>(arr: T[]): T[] { | ||
return [...new Set(arr)]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { | ||
Connection, | ||
PublicKey, | ||
sendAndConfirmTransaction, | ||
Signer, | ||
Transaction, | ||
TransactionInstruction, | ||
} from "@solana/web3.js"; | ||
|
||
import { Owner } from "./owner"; | ||
|
||
interface TxBuilderInit { | ||
connection: Connection; | ||
feePayer: PublicKey; | ||
owner?: Owner; | ||
signAllTransactions?: (transactions: Transaction[]) => Promise<Transaction[]>; | ||
} | ||
|
||
export class TxBuilder { | ||
private connection: Connection; | ||
private owner?: Owner; | ||
private instructions: TransactionInstruction[] = []; | ||
private endInstructions: TransactionInstruction[] = []; | ||
private signers: Signer[] = []; | ||
private feePayer: PublicKey; | ||
private signAllTransactions?: (transactions: Transaction[]) => Promise<Transaction[]>; | ||
|
||
constructor(params: TxBuilderInit) { | ||
this.connection = params.connection; | ||
this.feePayer = params.feePayer; | ||
this.signAllTransactions = params.signAllTransactions; | ||
this.owner = params.owner; | ||
} | ||
|
||
public addInstruction({ | ||
instructions = [], | ||
endInstructions = [], | ||
signers = [], | ||
}: { | ||
instructions?: TransactionInstruction[]; | ||
endInstructions?: TransactionInstruction[]; | ||
signers?: Signer[]; | ||
}): TxBuilder { | ||
this.instructions.push(...instructions); | ||
this.endInstructions.push(...endInstructions); | ||
this.signers.push(...signers); | ||
return this; | ||
} | ||
|
||
public async build(): Promise<{ | ||
transaction: Transaction; | ||
signers: Signer[]; | ||
excute: () => Promise<string>; | ||
}> { | ||
const recentBlockHash = await getRecentBlockhash(this.connection); | ||
|
||
const transaction = new Transaction(); | ||
transaction.recentBlockhash = recentBlockHash; | ||
transaction.add(...this.instructions, ...this.endInstructions); | ||
transaction.feePayer = this.feePayer; | ||
|
||
return { | ||
transaction, | ||
signers: this.signers, | ||
excute: async (): Promise<string> => { | ||
if (this.owner) { | ||
return sendAndConfirmTransaction(this.connection, transaction, this.signers); | ||
} | ||
if (this.signAllTransactions) { | ||
const signedTx = await this.signAllTransactions([transaction]); | ||
return this.connection.sendRawTransaction(signedTx[0].serialize()); | ||
} | ||
throw new Error("please connect wallet first"); | ||
}, | ||
}; | ||
} | ||
} | ||
|
||
export async function getRecentBlockhash(connection: Connection): Promise<string> { | ||
try { | ||
return (await connection.getLatestBlockhash?.())?.blockhash || (await connection.getRecentBlockhash()).blockhash; | ||
} catch { | ||
return (await connection.getRecentBlockhash()).blockhash; | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.