patch anchor's simulate fn so signing is required for simulation (#106)

This commit is contained in:
tjshipe 2022-07-14 02:42:21 -04:00 committed by GitHub
parent 97d936c9ca
commit fcf3da0a9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 11 deletions

View File

@ -1,5 +1,6 @@
import { Jupiter } from '@jup-ag/core';
import { AnchorProvider, BN, Program, Provider } from '@project-serum/anchor';
import { simulateTransaction } from '@project-serum/anchor/dist/cjs/utils/rpc';
import { getFeeRates, getFeeTier } from '@project-serum/serum';
import { Order } from '@project-serum/serum/lib/market';
import {
@ -50,6 +51,7 @@ import {
toNativeDecimals,
toU64,
} from './utils';
import { simulate } from './utils/anchor';
// TODO: replace ui values with native as input wherever possible
// TODO: replace token/market names with token or market indices
@ -440,7 +442,10 @@ export class MangoClient {
mangoAccount: MangoAccount,
): Promise<MangoAccountData> {
const healthRemainingAccounts: PublicKey[] =
await this.buildHealthRemainingAccounts(group, mangoAccount);
this.buildHealthRemainingAccounts(group, mangoAccount);
// Use our custom simulate fn in utils/anchor.ts so signing the tx is not required
this.program.provider.simulate = simulate;
const res = await this.program.methods
.computeAccountData()
@ -454,7 +459,6 @@ export class MangoClient {
({ pubkey: pk, isWritable: false, isSigner: false } as AccountMeta),
),
)
.signers([])
.simulate();
return MangoAccountData.from(
@ -508,7 +512,7 @@ export class MangoClient {
}
const healthRemainingAccounts: PublicKey[] =
await this.buildHealthRemainingAccounts(group, mangoAccount, [bank]);
this.buildHealthRemainingAccounts(group, mangoAccount, [bank]);
return await this.program.methods
.tokenDeposit(toNativeDecimals(amount, bank.mintDecimals))
@ -551,7 +555,7 @@ export class MangoClient {
);
const healthRemainingAccounts: PublicKey[] =
await this.buildHealthRemainingAccounts(group, mangoAccount, [bank]);
this.buildHealthRemainingAccounts(group, mangoAccount, [bank]);
return await this.program.methods
.tokenWithdraw(toNativeDecimals(amount, bank.mintDecimals), allowBorrow)
@ -586,7 +590,7 @@ export class MangoClient {
);
const healthRemainingAccounts: PublicKey[] =
await this.buildHealthRemainingAccounts(group, mangoAccount, [bank]);
this.buildHealthRemainingAccounts(group, mangoAccount, [bank]);
return await this.program.methods
.tokenWithdraw(new BN(nativeAmount), allowBorrow)
@ -774,7 +778,7 @@ export class MangoClient {
);
const healthRemainingAccounts: PublicKey[] =
await this.buildHealthRemainingAccounts(group, mangoAccount);
this.buildHealthRemainingAccounts(group, mangoAccount);
const limitPrice = serum3MarketExternal.priceNumberToLots(price);
const maxBaseQuantity = serum3MarketExternal.baseSizeNumberToLots(size);
@ -1131,7 +1135,7 @@ export class MangoClient {
const perpMarket = group.perpMarketsMap.get(perpMarketName)!;
const healthRemainingAccounts: PublicKey[] =
await this.buildHealthRemainingAccounts(group, mangoAccount);
this.buildHealthRemainingAccounts(group, mangoAccount);
let [nativePrice, nativeQuantity] = perpMarket.uiToNativePriceQuantity(
price,
@ -1193,7 +1197,7 @@ export class MangoClient {
if (!inputBank || !outputBank) throw new Error('Invalid token');
const healthRemainingAccounts: PublicKey[] =
await this.buildHealthRemainingAccounts(group, mangoAccount, [
this.buildHealthRemainingAccounts(group, mangoAccount, [
inputBank,
outputBank,
]);
@ -1438,7 +1442,7 @@ export class MangoClient {
if (!inputBank || !outputBank) throw new Error('Invalid token');
const healthRemainingAccounts: PublicKey[] =
await this.buildHealthRemainingAccounts(group, mangoAccount, [
this.buildHealthRemainingAccounts(group, mangoAccount, [
inputBank,
outputBank,
]);
@ -1645,7 +1649,7 @@ export class MangoClient {
/// private
public async buildHealthRemainingAccounts(
public buildHealthRemainingAccounts(
group: Group,
mangoAccount: MangoAccount,
banks?: Bank[] /** TODO for serum3PlaceOrder we are just ingoring this atm */,

View File

@ -131,7 +131,7 @@ async function main() {
// flash loan start ix - takes a loan for source token,
// flash loan end ix - returns increase in all token account's amounts to respective vaults,
const healthRemainingAccounts = await client.buildHealthRemainingAccounts(
const healthRemainingAccounts = client.buildHealthRemainingAccounts(
group,
mangoAccount,
[sourceBank, targetBank], // we would be taking a sol loan potentially

View File

@ -0,0 +1,42 @@
import {
simulateTransaction,
SuccessfulTxSimulationResponse,
} from '@project-serum/anchor/dist/cjs/utils/rpc';
import {
Signer,
PublicKey,
Transaction,
Commitment,
SimulatedTransactionResponse,
} from '@solana/web3.js';
class SimulateError extends Error {
constructor(
readonly simulationResponse: SimulatedTransactionResponse,
message?: string,
) {
super(message);
}
}
export async function simulate(
tx: Transaction,
signers?: Signer[],
commitment?: Commitment,
includeAccounts?: boolean | PublicKey[],
): Promise<SuccessfulTxSimulationResponse> {
tx.feePayer = this.wallet.publicKey;
tx.recentBlockhash = (
await this.connection.getLatestBlockhash(
commitment ?? this.connection.commitment,
)
).blockhash;
const result = await simulateTransaction(this.connection, tx);
if (result.value.err) {
throw new SimulateError(result.value);
}
return result.value;
}