Skip to content

Commit ebf10c2

Browse files
committed
add fee transfer ix to message example
1 parent 4511053 commit ebf10c2

File tree

4 files changed

+35
-26
lines changed

4 files changed

+35
-26
lines changed

platforms/solana/protocols/core/src/core.ts

+20-6
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ import {
3434
createPostVaaInstruction,
3535
createReadOnlyWormholeProgramInterface,
3636
createVerifySignaturesInstructions,
37+
createBridgeFeeTransferInstruction,
3738
derivePostedVaaKey,
3839
getWormholeBridgeData,
40+
BridgeData,
3941
} from './utils';
4042

4143
const SOLANA_SEQ_LOG = 'Program log: Sequence: ';
@@ -46,6 +48,7 @@ export class SolanaWormholeCore<N extends Network, C extends SolanaChains>
4648
readonly chainId: ChainId;
4749
readonly coreBridge: Program<WormholeCoreContract>;
4850
readonly address: string;
51+
protected bridgeData?: BridgeData;
4952

5053
constructor(
5154
readonly network: N,
@@ -79,6 +82,7 @@ export class SolanaWormholeCore<N extends Network, C extends SolanaChains>
7982
throw new Error(
8083
`Network mismatch for chain ${chain}: ${conf.network} != ${network}`,
8184
);
85+
8286
return new SolanaWormholeCore(
8387
network as N,
8488
chain,
@@ -88,11 +92,14 @@ export class SolanaWormholeCore<N extends Network, C extends SolanaChains>
8892
}
8993

9094
async getMessageFee(): Promise<bigint> {
91-
const bd = await getWormholeBridgeData(
92-
this.connection,
93-
this.coreBridge.programId,
94-
);
95-
return bd.config.fee;
95+
// cache lookups since this should not change frequently
96+
if (!this.bridgeData)
97+
this.bridgeData = await getWormholeBridgeData(
98+
this.connection,
99+
this.coreBridge.programId,
100+
);
101+
102+
return this.bridgeData.config.fee;
96103
}
97104

98105
async *publishMessage(
@@ -113,11 +120,18 @@ export class SolanaWormholeCore<N extends Network, C extends SolanaChains>
113120
consistencyLevel,
114121
);
115122

123+
const fee = await this.getMessageFee();
124+
const feeTransferIx = createBridgeFeeTransferInstruction(
125+
this.coreBridge.programId,
126+
payer,
127+
fee,
128+
);
129+
116130
const { blockhash } = await SolanaPlatform.latestBlock(this.connection);
117131
const transaction = new Transaction();
118132
transaction.recentBlockhash = blockhash;
119133
transaction.feePayer = payer;
120-
transaction.add(postMsgIx);
134+
transaction.add(feeTransferIx, postMsgIx);
121135
transaction.partialSign(messageAccount);
122136

123137
yield this.createUnsignedTx(transaction, 'Core.PublishMessage');

platforms/solana/protocols/core/src/utils/instructions/feeTransfer.ts

+4-12
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,16 @@
11
import {
2-
Commitment,
3-
Connection,
42
PublicKey,
53
PublicKeyInitData,
64
SystemProgram,
75
TransactionInstruction,
86
} from '@solana/web3.js';
9-
import { deriveFeeCollectorKey, getWormholeBridgeData } from '../accounts';
7+
import { deriveFeeCollectorKey } from '../accounts';
108

11-
export async function createBridgeFeeTransferInstruction(
12-
connection: Connection,
9+
export function createBridgeFeeTransferInstruction(
1310
wormholeProgramId: PublicKeyInitData,
1411
payer: PublicKeyInitData,
15-
commitment?: Commitment,
16-
): Promise<TransactionInstruction> {
17-
const fee = await getWormholeBridgeData(
18-
connection,
19-
wormholeProgramId,
20-
commitment,
21-
).then((data) => data.config.fee);
12+
fee: bigint,
13+
): TransactionInstruction {
2214
return SystemProgram.transfer({
2315
fromPubkey: new PublicKey(payer),
2416
toPubkey: deriveFeeCollectorKey(wormholeProgramId),

platforms/solana/protocols/tokenBridge/src/tokenBridge.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -216,11 +216,13 @@ export class SolanaTokenBridge<N extends Network, C extends SolanaChains>
216216
// TODO: createNonce().readUInt32LE(0);
217217
const nonce = 0;
218218

219-
const transferIx = await coreUtils.createBridgeFeeTransferInstruction(
220-
this.connection,
219+
const fee = await this.coreBridge.getMessageFee();
220+
const transferIx = coreUtils.createBridgeFeeTransferInstruction(
221221
this.coreBridge.address,
222-
senderAddress,
222+
payer,
223+
fee,
223224
);
225+
224226
const messageKey = Keypair.generate();
225227
const attestIx = createAttestTokenInstruction(
226228
this.connection,

platforms/solana/src/platform.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -166,18 +166,17 @@ export class SolanaPlatform<N extends Network> extends PlatformContext<
166166
// recoverable. Currently handles:
167167
// - Blockhash not found (blockhash too new for the node we submitted to)
168168
// - Not enough bytes (storage account not seen yet)
169-
170169
private static async sendWithRetry(
171170
rpc: Connection,
172-
stxns: SignedTx,
171+
stxn: SignedTx,
173172
opts: SendOptions,
174173
retries: number = 3,
175174
): Promise<string> {
176175
// Shouldnt get hit but just in case
177176
if (!retries) throw new Error('Too many retries');
178177

179178
try {
180-
const txid = await rpc.sendRawTransaction(stxns.tx, opts);
179+
const txid = await rpc.sendRawTransaction(stxn, opts);
181180
return txid;
182181
} catch (e) {
183182
retries -= 1;
@@ -195,7 +194,7 @@ export class SolanaPlatform<N extends Network> extends PlatformContext<
195194

196195
// Blockhash not found _yet_
197196
if (emsg.includes('Blockhash not found'))
198-
return this.sendWithRetry(rpc, stxns, opts, retries);
197+
return this.sendWithRetry(rpc, stxn, opts, retries);
199198

200199
// Find the log message with the error details
201200
const loggedErr = e.logs.find((log) =>
@@ -204,7 +203,9 @@ export class SolanaPlatform<N extends Network> extends PlatformContext<
204203

205204
// Probably caused by storage account not seen yet
206205
if (loggedErr && loggedErr.includes('Not enough bytes'))
207-
return this.sendWithRetry(rpc, stxns, opts, retries);
206+
return this.sendWithRetry(rpc, stxn, opts, retries);
207+
208+
throw e;
208209
}
209210
}
210211

0 commit comments

Comments
 (0)