diff --git a/modules/sdk-coin-sol/src/lib/ataInitializationBuilder.ts b/modules/sdk-coin-sol/src/lib/ataInitializationBuilder.ts index 9fc0d3d6b3..2578f01a6e 100644 --- a/modules/sdk-coin-sol/src/lib/ataInitializationBuilder.ts +++ b/modules/sdk-coin-sol/src/lib/ataInitializationBuilder.ts @@ -166,6 +166,15 @@ export class AtaInitializationBuilder extends TransactionBuilder { } this._instructionsData = []; + if (this._priorityFee && this._priorityFee !== Number(0)) { + this._instructionsData.push({ + type: InstructionBuilderTypes.SetPriorityFee, + params: { + fee: this._priorityFee, + }, + }); + } + await Promise.all( this._tokenAssociateRecipients.map(async (recipient) => { let tokenAddress: string; diff --git a/modules/sdk-coin-sol/src/lib/stakingActivateBuilder.ts b/modules/sdk-coin-sol/src/lib/stakingActivateBuilder.ts index 40e5c60074..e904fb42f2 100644 --- a/modules/sdk-coin-sol/src/lib/stakingActivateBuilder.ts +++ b/modules/sdk-coin-sol/src/lib/stakingActivateBuilder.ts @@ -126,7 +126,16 @@ export class StakingActivateBuilder extends TransactionBuilder { extraParams: this._extraParams, }, }; - this._instructionsData = [stakingAccountData]; + this._instructionsData = + this._priorityFee && this._priorityFee !== Number(0) + ? [ + { + type: InstructionBuilderTypes.SetPriorityFee, + params: { fee: this._priorityFee }, + }, + stakingAccountData, + ] + : [stakingAccountData]; return await super.buildImplementation(); } diff --git a/modules/sdk-coin-sol/src/lib/stakingDeactivateBuilder.ts b/modules/sdk-coin-sol/src/lib/stakingDeactivateBuilder.ts index 43ca7302ec..c6831cd96b 100644 --- a/modules/sdk-coin-sol/src/lib/stakingDeactivateBuilder.ts +++ b/modules/sdk-coin-sol/src/lib/stakingDeactivateBuilder.ts @@ -229,6 +229,13 @@ export class StakingDeactivateBuilder extends TransactionBuilder { this._instructionsData.push(stakingDeactivateData); } + if (this._priorityFee && this._priorityFee !== Number(0)) { + this._instructionsData.unshift({ + type: InstructionBuilderTypes.SetPriorityFee, + params: { fee: this._priorityFee }, + }); + } + return await super.buildImplementation(); } } diff --git a/modules/sdk-coin-sol/src/lib/stakingDelegateBuilder.ts b/modules/sdk-coin-sol/src/lib/stakingDelegateBuilder.ts index f6e4e4abca..a504e5f9ba 100644 --- a/modules/sdk-coin-sol/src/lib/stakingDelegateBuilder.ts +++ b/modules/sdk-coin-sol/src/lib/stakingDelegateBuilder.ts @@ -122,6 +122,12 @@ export class StakingDelegateBuilder extends TransactionBuilder { }; this._instructionsData = [stakingAccountData]; } + if (this._priorityFee && this._priorityFee !== Number(0)) { + this._instructionsData.unshift({ + type: InstructionBuilderTypes.SetPriorityFee, + params: { fee: this._priorityFee }, + }); + } return await super.buildImplementation(); } } diff --git a/modules/sdk-coin-sol/src/lib/stakingWithdrawBuilder.ts b/modules/sdk-coin-sol/src/lib/stakingWithdrawBuilder.ts index 064cede2df..f350ea2331 100644 --- a/modules/sdk-coin-sol/src/lib/stakingWithdrawBuilder.ts +++ b/modules/sdk-coin-sol/src/lib/stakingWithdrawBuilder.ts @@ -79,7 +79,16 @@ export class StakingWithdrawBuilder extends TransactionBuilder { amount: this._amount, }, }; - this._instructionsData = [stakingWithdrawData]; + this._instructionsData = + this._priorityFee && this._priorityFee !== Number(0) + ? [ + { + type: InstructionBuilderTypes.SetPriorityFee, + params: { fee: this._priorityFee }, + }, + stakingWithdrawData, + ] + : [stakingWithdrawData]; return await super.buildImplementation(); } diff --git a/modules/sdk-coin-sol/src/lib/transferBuilder.ts b/modules/sdk-coin-sol/src/lib/transferBuilder.ts index 1423ad0cca..22dab30cba 100644 --- a/modules/sdk-coin-sol/src/lib/transferBuilder.ts +++ b/modules/sdk-coin-sol/src/lib/transferBuilder.ts @@ -75,7 +75,18 @@ export class TransferBuilder extends TransactionBuilder { }, }; }); - this._instructionsData = transferData; + // Prepend the priority fee instruction (CHALO-485) so native SOL transfers can be + // prioritized during network congestion. Omitted when no priority fee is set (0). + this._instructionsData = + this._priorityFee && this._priorityFee !== Number(0) + ? [ + { + type: InstructionBuilderTypes.SetPriorityFee, + params: { fee: this._priorityFee }, + }, + ...transferData, + ] + : transferData; return await super.buildImplementation(); } diff --git a/modules/sdk-coin-sol/src/lib/transferBuilderV2.ts b/modules/sdk-coin-sol/src/lib/transferBuilderV2.ts index e58ce66969..8451f690c4 100644 --- a/modules/sdk-coin-sol/src/lib/transferBuilderV2.ts +++ b/modules/sdk-coin-sol/src/lib/transferBuilderV2.ts @@ -271,13 +271,9 @@ export class TransferBuilderV2 extends TransactionBuilder { : []; let addPriorityFeeInstruction: SetPriorityFee; - // If there are createAtaInstructions, then token is involved and we need to add a priority fee instruction if (!this._priorityFee || this._priorityFee === Number(0)) { this._instructionsData = [...createAtaInstructions, ...thawInstructions, ...sendInstructions]; - } else if ( - createAtaInstructions.length !== 0 || - sendInstructions.some((instruction) => instruction.type === InstructionBuilderTypes.TokenTransfer) - ) { + } else { addPriorityFeeInstruction = { type: InstructionBuilderTypes.SetPriorityFee, params: { diff --git a/modules/sdk-coin-sol/test/unit/transactionBuilder/transferBuilder.ts b/modules/sdk-coin-sol/test/unit/transactionBuilder/transferBuilder.ts index 4f566ab5de..a72b92c762 100644 --- a/modules/sdk-coin-sol/test/unit/transactionBuilder/transferBuilder.ts +++ b/modules/sdk-coin-sol/test/unit/transactionBuilder/transferBuilder.ts @@ -1,5 +1,6 @@ import { getBuilderFactory } from '../getBuilderFactory'; import { KeyPair, Utils } from '../../../src'; +import { TransactionType } from '@bitgo/sdk-core'; import should from 'should'; import * as testData from '../../resources/sol'; @@ -231,6 +232,24 @@ describe('Sol Transfer Builder', () => { should.equal(Utils.isValidRawTransaction(rawTx), true); should.equal(rawTx, testData.MULTI_TRANSFER_SIGNED); }); + + it('build a signed transfer with priority fee', async () => { + const txBuilder = transferBuilder(); + txBuilder.sender(authAccount.pub); + txBuilder.send({ address: nonceAccount.pub, amount }); + txBuilder.setPriorityFee({ amount: 50000 }); + txBuilder.sign({ key: authAccount.prv }); + const tx = await txBuilder.build(); + tx.type.should.equal(TransactionType.Send); + const rawTx = tx.toBroadcastFormat(); + should.equal(Utils.isValidRawTransaction(rawTx), true); + const onChainInstructions = (tx as any).solTransaction.instructions; + onChainInstructions + .some( + (ix: any) => ix.programId.toString() === 'ComputeBudget111111111111111111111111111111' && ix.data.length > 0 + ) + .should.equal(true); + }); }); describe('Fail', () => { it('for invalid sender', () => {