Skip to content

Commit f52e719

Browse files
authored
#1697: add priority fee to Solana transactions (#1755)
* set priority fee for solana transactions * always set compute unit limit & price * set fee to 75th percentile of recent fees paid * include mintAddress * fix try/catch
1 parent 50d6705 commit f52e719

File tree

1 file changed

+102
-31
lines changed

1 file changed

+102
-31
lines changed

sdk/src/contexts/solana/context.ts

+102-31
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
import {
2424
clusterApiUrl,
2525
Commitment,
26+
ComputeBudgetProgram,
2627
Connection,
2728
Keypair,
2829
PublicKey,
@@ -77,6 +78,9 @@ import {
7778
const SOLANA_SEQ_LOG = 'Program log: Sequence: ';
7879
const SOLANA_CHAIN_NAME = MAINNET_CONFIG.chains.solana!.key;
7980

81+
// Add priority fee according to 75th percentile of recent fees paid
82+
const SOLANA_FEE_PERCENTILE = 0.75;
83+
8084
const SOLANA_MAINNET_EMMITER_ID =
8185
'ec7372995d5cc8732397fb0ad35c0121e0eaa90d26f828a534cab54391b3a4f5';
8286
const SOLANA_TESTNET_EMITTER_ID =
@@ -273,7 +277,15 @@ export class SolanaContext<
273277
payerPublicKey,
274278
tokenPublicKey,
275279
);
276-
const transaction = new Transaction().add(createAccountInst);
280+
const transaction = new Transaction();
281+
transaction.add(
282+
...(await this.determineComputeBudget([
283+
tokenPublicKey,
284+
associatedPublicKey,
285+
])),
286+
);
287+
transaction.add(createAccountInst);
288+
277289
const { blockhash } = await this.connection.getLatestBlockhash(commitment);
278290
transaction.recentBlockhash = blockhash;
279291
transaction.feePayer = payerPublicKey;
@@ -387,6 +399,8 @@ export class SolanaContext<
387399

388400
const { blockhash } = await this.connection.getLatestBlockhash(commitment);
389401
const transaction = new Transaction();
402+
transaction.add(...(await this.determineComputeBudget([NATIVE_MINT])));
403+
390404
transaction.recentBlockhash = blockhash;
391405
transaction.feePayer = payerPublicKey;
392406
transaction.add(
@@ -517,10 +531,14 @@ export class SolanaContext<
517531
recipientAddress,
518532
recipientChainId,
519533
);
520-
const transaction = new Transaction().add(
521-
approvalIx,
522-
tokenBridgeTransferIx,
534+
const transaction = new Transaction();
535+
transaction.add(
536+
...(await this.determineComputeBudget([
537+
new PublicKey(fromAddress),
538+
new PublicKey(mintAddress),
539+
])),
523540
);
541+
transaction.add(approvalIx, tokenBridgeTransferIx);
524542
const { blockhash } = await this.connection.getLatestBlockhash(commitment);
525543
transaction.recentBlockhash = blockhash;
526544
transaction.feePayer = new PublicKey(senderAddress);
@@ -936,6 +954,7 @@ export class SolanaContext<
936954
parsed.tokenAddress,
937955
);
938956
const transaction = new Transaction();
957+
transaction.add(...(await this.determineComputeBudget([mint])));
939958
const recipientTokenAccount = getAssociatedTokenAddressSync(
940959
mint,
941960
recipient,
@@ -1047,15 +1066,21 @@ export class SolanaContext<
10471066
const recipientChainId = this.context.toChainId(recipientChain);
10481067
const nonce = createNonce().readUint32LE();
10491068
const transaction = new Transaction();
1050-
let transferIx: TransactionInstruction;
1069+
10511070
if (token === NATIVE || token.chain === SOLANA_CHAIN_NAME) {
10521071
const mint = token === NATIVE ? NATIVE_MINT : token.address;
10531072
const wrapToken = token === NATIVE;
1073+
1074+
let writableAddresses: PublicKey[] = [NATIVE_MINT];
1075+
10541076
if (wrapToken) {
10551077
const ata = getAssociatedTokenAddressSync(
10561078
NATIVE_MINT,
10571079
new PublicKey(senderAddress),
10581080
);
1081+
1082+
writableAddresses.push(ata);
1083+
10591084
try {
10601085
await getAccount(this.connection, ata);
10611086
} catch (e: any) {
@@ -1073,37 +1098,49 @@ export class SolanaContext<
10731098
}
10741099
}
10751100
}
1076-
transferIx = await createTransferNativeTokensWithRelayInstruction(
1077-
this.connection,
1078-
relayer,
1079-
senderAddress,
1080-
token_bridge,
1081-
core,
1082-
mint,
1083-
BigInt(amount),
1084-
BigInt(toNativeToken),
1085-
formattedRecipient,
1086-
recipientChainId,
1087-
nonce,
1088-
wrapToken,
1101+
1102+
transaction.add(
1103+
...(await this.determineComputeBudget(writableAddresses)),
1104+
);
1105+
transaction.add(
1106+
await createTransferNativeTokensWithRelayInstruction(
1107+
this.connection,
1108+
relayer,
1109+
senderAddress,
1110+
token_bridge,
1111+
core,
1112+
mint,
1113+
BigInt(amount),
1114+
BigInt(toNativeToken),
1115+
formattedRecipient,
1116+
recipientChainId,
1117+
nonce,
1118+
wrapToken,
1119+
),
10891120
);
10901121
} else {
10911122
const mint = await this.mustGetForeignAsset(token, sendingChain);
1092-
transferIx = await createTransferWrappedTokensWithRelayInstruction(
1093-
this.connection,
1094-
relayer,
1095-
senderAddress,
1096-
token_bridge,
1097-
core,
1098-
mint,
1099-
BigInt(amount),
1100-
BigInt(toNativeToken),
1101-
formattedRecipient,
1102-
recipientChainId,
1103-
nonce,
1123+
1124+
transaction.add(
1125+
...(await this.determineComputeBudget([new PublicKey(mint)])),
1126+
);
1127+
transaction.add(
1128+
await createTransferWrappedTokensWithRelayInstruction(
1129+
this.connection,
1130+
relayer,
1131+
senderAddress,
1132+
token_bridge,
1133+
core,
1134+
mint,
1135+
BigInt(amount),
1136+
BigInt(toNativeToken),
1137+
formattedRecipient,
1138+
recipientChainId,
1139+
nonce,
1140+
),
11041141
);
11051142
}
1106-
transaction.add(transferIx);
1143+
11071144
const { blockhash } = await this.connection.getLatestBlockhash('finalized');
11081145
transaction.recentBlockhash = blockhash;
11091146
transaction.feePayer = new PublicKey(senderAddress);
@@ -1176,4 +1213,38 @@ export class SolanaContext<
11761213
chain: 'solana',
11771214
};
11781215
}
1216+
1217+
async determineComputeBudget(
1218+
lockedWritableAccounts: PublicKey[] = [],
1219+
): Promise<TransactionInstruction[]> {
1220+
let fee = 100_000; // Set fee to 100,000 microlamport by default
1221+
1222+
try {
1223+
const recentFeesResponse =
1224+
await this.connection?.getRecentPrioritizationFees({
1225+
lockedWritableAccounts,
1226+
});
1227+
1228+
if (recentFeesResponse) {
1229+
// Get 75th percentile fee paid in recent slots
1230+
const recentFees = recentFeesResponse
1231+
.map((dp) => dp.prioritizationFee)
1232+
.sort((a, b) => a - b);
1233+
fee = recentFees[Math.floor(recentFees.length * SOLANA_FEE_PERCENTILE)];
1234+
}
1235+
} catch (e) {
1236+
console.error('Error fetching Solana recent fees', e);
1237+
}
1238+
1239+
console.info(`Setting Solana compute unit price to ${fee} microLamports`);
1240+
1241+
return [
1242+
ComputeBudgetProgram.setComputeUnitLimit({
1243+
units: 250_000,
1244+
}),
1245+
ComputeBudgetProgram.setComputeUnitPrice({
1246+
microLamports: fee,
1247+
}),
1248+
];
1249+
}
11791250
}

0 commit comments

Comments
 (0)