Skip to content

Commit

Permalink
add sign and send signer for solana
Browse files Browse the repository at this point in the history
  • Loading branch information
barnjamin committed Jan 2, 2024
1 parent 46b01d5 commit f27f51c
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 12 deletions.
5 changes: 1 addition & 4 deletions platforms/solana/protocols/core/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export class SolanaWormholeCore<N extends Network, C extends SolanaChains>
signatureSet.publicKey,
);

// Create a new transaction for every 2 signatures we have to Verify
// Create a new transaction for every 2 instructions
for (let i = 0; i < verifySignaturesInstructions.length; i += 2) {
const verifySigTx = new Transaction().add(
...verifySignaturesInstructions.slice(i, i + 2),
Expand All @@ -155,9 +155,6 @@ export class SolanaWormholeCore<N extends Network, C extends SolanaChains>
yield this.createUnsignedTx(verifySigTx, 'Core.VerifySignature', true);
}

// TODO: if VAA is already posted, just, like, dont post it again man
// if(this.connection.getAccountInfo(postedVaaAddress))

// Finally create the VAA posting transaction
const postVaaTx = new Transaction().add(
createPostVaaInstruction(
Expand Down
13 changes: 5 additions & 8 deletions platforms/solana/src/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,14 @@ export class SolanaPlatform<N extends Network> extends PlatformContext<
rpc: Connection,
stxns: SignedTx[],
): Promise<TxHash[]> {
const { blockhash, lastValidBlockHeight } = await this.latestBlock(rpc);

const txhashes = await Promise.all(
stxns.map((stxn) => {
return rpc.sendRawTransaction(stxn);
}),
);

const { blockhash, lastValidBlockHeight } = await this.latestBlockhash(rpc);

await Promise.all(
txhashes.map((txid) => {
const bhs: BlockheightBasedTransactionConfirmationStrategy = {
Expand All @@ -187,23 +187,20 @@ export class SolanaPlatform<N extends Network> extends PlatformContext<
return txhashes;
}

static async latestBlockhash(
static async latestBlock(
rpc: Connection,
commitment?: Commitment,
): Promise<{ blockhash: string; lastValidBlockHeight: number }> {
return rpc.getLatestBlockhash(commitment ?? rpc.commitment);
}

static async getLatestBlock(rpc: Connection): Promise<number> {
const { lastValidBlockHeight } = await this.latestBlockhash(rpc);
const { lastValidBlockHeight } = await this.latestBlock(rpc);
return lastValidBlockHeight;
}

static async getLatestFinalizedBlock(rpc: Connection): Promise<number> {
const { lastValidBlockHeight } = await this.latestBlockhash(
rpc,
'finalized',
);
const { lastValidBlockHeight } = await this.latestBlock(rpc, 'finalized');
return lastValidBlockHeight;
}

Expand Down
1 change: 1 addition & 0 deletions platforms/solana/src/testing/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './signer';
export * from './sendSigner';
94 changes: 94 additions & 0 deletions platforms/solana/src/testing/sendSigner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { Connection, Keypair, Transaction } from '@solana/web3.js';
import {
SignAndSendSigner,
Signer,
UnsignedTransaction,
encoding,
} from '@wormhole-foundation/connect-sdk';
import { Network } from '@wormhole-foundation/sdk-base/src';
import { SolanaPlatform } from '../platform';
import { SolanaChains } from '../types';
import { SolanaUnsignedTransaction } from '../unsignedTransaction';

// returns a SignOnlySigner for the Solana platform
export async function getSolanaSignAndSendSigner(
rpc: Connection,
privateKey: string,
): Promise<Signer> {
const [_, chain] = await SolanaPlatform.chainFromRpc(rpc);
return new SolanaSendSigner(
rpc,
chain,
Keypair.fromSecretKey(encoding.b58.decode(privateKey)),
);
}

export class SolanaSendSigner<
N extends Network,
C extends SolanaChains = 'Solana',
> implements SignAndSendSigner<N, C>
{
constructor(
private _rpc: Connection,
private _chain: C,
private _keypair: Keypair,
private _debug: boolean = false,
) {}

chain(): C {
return this._chain;
}

address(): string {
return this._keypair.publicKey.toBase58();
}

async signAndSend(tx: UnsignedTransaction[]): Promise<any[]> {
const txids: string[] = [];

const { blockhash, lastValidBlockHeight } =
await SolanaPlatform.latestBlock(this._rpc);

for (const txn of tx) {
const { description, transaction } = txn as SolanaUnsignedTransaction<
N,
C
>;
console.log(`Signing: ${description} for ${this.address()}`);

if (this._debug) {
const st = transaction as Transaction;
console.log(st.signatures);
console.log(st.feePayer);
st.instructions.forEach((ix) => {
console.log('Program', ix.programId.toBase58());
console.log('Data: ', ix.data.toString('hex'));
console.log(
'Keys: ',
ix.keys.map((k) => [k, k.pubkey.toBase58()]),
);
});
}

transaction.partialSign(this._keypair);

const txid = await this._rpc.sendRawTransaction(transaction.serialize(), {
// skipPreflight: true,
// preflightCommitment: this._rpc.commitment,
maxRetries: 5,
});

console.log(`Sent: ${description} for ${this.address()}`);

await this._rpc.confirmTransaction({
signature: txid,
blockhash,
lastValidBlockHeight,
});

txids.push(txid);
}

return txids;
}
}

0 comments on commit f27f51c

Please sign in to comment.