mirror of
https://github.com/trezor/trezor-suite.git
synced 2026-03-03 05:55:03 +01:00
chore(blockchain-link): set max CU limit for sol priority fee simulation
This commit is contained in:
@@ -71,6 +71,7 @@
|
||||
"worker-loader": "^3.0.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"@solana-program/compute-budget": "^0.8.0",
|
||||
"@solana-program/stake": "^0.2.1",
|
||||
"@solana-program/token": "^0.5.1",
|
||||
"@solana-program/token-2022": "^0.4.2",
|
||||
|
||||
@@ -73,12 +73,6 @@ const THROTTLE_OPTIONS: ThrottledTransportOptions = {
|
||||
interval: 100,
|
||||
};
|
||||
|
||||
const DEFAULT_PRIORITY_FEE = {
|
||||
computeUnitPrice: '0',
|
||||
computeUnitLimit: '0',
|
||||
fee: '0',
|
||||
};
|
||||
|
||||
export type SolanaAPI = Readonly<{
|
||||
clusterUrl: ClusterUrl;
|
||||
rpc: RpcMainnet<SolanaRpcApiMainnet>;
|
||||
@@ -556,11 +550,7 @@ const estimateFee = async (request: Request<MessageTypes.EstimateFee>) => {
|
||||
decompiledTransactionMessage,
|
||||
message,
|
||||
transaction.signatures,
|
||||
).catch(err => {
|
||||
console.warn('getPriorityFee failed:', err);
|
||||
|
||||
return DEFAULT_PRIORITY_FEE;
|
||||
});
|
||||
);
|
||||
|
||||
const baseFee = await getBaseFee(api.rpc, message);
|
||||
|
||||
|
||||
@@ -16,8 +16,13 @@ import {
|
||||
isWritableRole,
|
||||
pipe,
|
||||
} from '@solana/kit';
|
||||
import {
|
||||
MAX_COMPUTE_UNIT_LIMIT,
|
||||
SET_COMPUTE_UNIT_LIMIT_DISCRIMINATOR,
|
||||
} from '@solana-program/compute-budget';
|
||||
|
||||
import { COMPUTE_BUDGET_PROGRAM_ID } from '@trezor/blockchain-link-utils/src/solana';
|
||||
import { safeBigIntStringify } from '@trezor/utils';
|
||||
import { BigNumber } from '@trezor/utils/src/bigNumber';
|
||||
|
||||
const DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = BigInt(300_000); // micro-lamports, value taken from other wallets
|
||||
@@ -33,6 +38,28 @@ const stripComputeBudgetInstructions = (message: CompiledTransactionMessage) =>
|
||||
),
|
||||
});
|
||||
|
||||
// increase compute unit limit to maximum for priority fee simulation
|
||||
// avoid simulation fail in case instructions are wrong (e.g. from backend)
|
||||
const bumpUnitLimitComputeBudgetInstructions = (
|
||||
message: CompiledTransactionMessage,
|
||||
): CompiledTransactionMessage => ({
|
||||
...message,
|
||||
instructions: message.instructions.map(ix => {
|
||||
if (
|
||||
message.staticAccounts[ix.programAddressIndex] === COMPUTE_BUDGET_PROGRAM_ID &&
|
||||
ix.data?.[0] === SET_COMPUTE_UNIT_LIMIT_DISCRIMINATOR
|
||||
) {
|
||||
const data = new Uint8Array(5);
|
||||
data[0] = SET_COMPUTE_UNIT_LIMIT_DISCRIMINATOR; // SetComputeUnitLimit
|
||||
new DataView(data.buffer).setUint32(1, MAX_COMPUTE_UNIT_LIMIT, true);
|
||||
|
||||
return { ...ix, data };
|
||||
}
|
||||
|
||||
return ix;
|
||||
}),
|
||||
});
|
||||
|
||||
export const getBaseFee = async (
|
||||
api: Rpc<GetFeeForMessageApi>,
|
||||
message: CompiledTransactionMessage,
|
||||
@@ -69,9 +96,10 @@ export const getPriorityFee = async (
|
||||
|
||||
// Reconstruct TX for simulation
|
||||
const messageBytes = pipe(
|
||||
compiledMessage,
|
||||
bumpUnitLimitComputeBudgetInstructions(compiledMessage),
|
||||
getCompiledTransactionMessageEncoder().encode,
|
||||
) as TransactionMessageBytes;
|
||||
|
||||
const rawTx = pipe(
|
||||
{
|
||||
messageBytes,
|
||||
@@ -82,12 +110,21 @@ export const getPriorityFee = async (
|
||||
) as Base64EncodedWireTransaction;
|
||||
|
||||
const simulated = await api
|
||||
.simulateTransaction(rawTx, { commitment: 'confirmed', encoding: 'base64' })
|
||||
.simulateTransaction(rawTx, {
|
||||
commitment: 'confirmed',
|
||||
encoding: 'base64',
|
||||
sigVerify: false,
|
||||
replaceRecentBlockhash: true,
|
||||
})
|
||||
.send();
|
||||
if (simulated.value.err != null || !simulated.value.unitsConsumed) {
|
||||
console.error('Could not simulate transaction:', JSON.stringify(simulated.value.err));
|
||||
throw new Error(`Could not simulate transaction: ${JSON.stringify(simulated.value.err)}`);
|
||||
|
||||
if (simulated.value.err != null || simulated.value.unitsConsumed == null) {
|
||||
const stringifiedError = safeBigIntStringify(simulated.value.err);
|
||||
|
||||
console.error('Could not simulate transaction:', stringifiedError);
|
||||
throw new Error(`Could not simulate transaction: ${stringifiedError}`);
|
||||
}
|
||||
|
||||
// Add 20% margin to the computed limit
|
||||
const computeUnitLimit = new BigNumber(simulated.value.unitsConsumed.toString())
|
||||
.times(1.2)
|
||||
|
||||
@@ -60,3 +60,4 @@ export * from './urlToOnion';
|
||||
export * from './zip';
|
||||
export * from './removeTrailingSlashes';
|
||||
export * from './getIntegerInRangeFromString';
|
||||
export * from './safeBigIntStringify';
|
||||
|
||||
2
packages/utils/src/safeBigIntStringify.ts
Normal file
2
packages/utils/src/safeBigIntStringify.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export const safeBigIntStringify = (v: unknown) =>
|
||||
JSON.stringify(v, (_k, val) => (typeof val === 'bigint' ? val.toString() : val));
|
||||
25
packages/utils/tests/safeBigIntStringify.test.ts
Normal file
25
packages/utils/tests/safeBigIntStringify.test.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { safeBigIntStringify } from '../src';
|
||||
|
||||
describe('safeStringify', () => {
|
||||
it('serializes regular objects normally', () => {
|
||||
const obj = { a: 1, b: 'text', c: true, d: null };
|
||||
expect(safeBigIntStringify(obj)).toBe(JSON.stringify(obj));
|
||||
});
|
||||
|
||||
it('converts BigInt values to strings', () => {
|
||||
const x = { val: 1234567890123456789n };
|
||||
const json = safeBigIntStringify(x);
|
||||
// Should not throw and should include quoted bigint
|
||||
expect(json).toBe('{"val":"1234567890123456789"}');
|
||||
});
|
||||
|
||||
it('serializes nested BigInt in arrays and objects', () => {
|
||||
const x = { arr: [1n, { nested: 2n }, 3] };
|
||||
expect(safeBigIntStringify(x)).toBe('{"arr":["1",{"nested":"2"},3]}');
|
||||
});
|
||||
|
||||
it('does not modify non-BigInt values', () => {
|
||||
const x = { num: 42, str: 'hello', bool: false };
|
||||
expect(safeBigIntStringify(x)).toBe(JSON.stringify(x));
|
||||
});
|
||||
});
|
||||
@@ -11854,6 +11854,7 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@trezor/blockchain-link@workspace:packages/blockchain-link"
|
||||
dependencies:
|
||||
"@solana-program/compute-budget": "npm:^0.8.0"
|
||||
"@solana-program/stake": "npm:^0.2.1"
|
||||
"@solana-program/token": "npm:^0.5.1"
|
||||
"@solana-program/token-2022": "npm:^0.4.2"
|
||||
|
||||
Reference in New Issue
Block a user