Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add additional post vaa detection support #2158

Draft
wants to merge 14 commits into
base: development
Choose a base branch
from
58 changes: 56 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"@mysten/sui.js": "^0.32.2",
"@nomad-xyz/multi-provider": "^1.1.0",
"@solana/spl-token": "^0.3.7",
"@solana/web3.js": "^1.73.0",
"@solana/web3.js": "^1.91.0",
"aptos": "1.5.0",
"axios": "^0.27.2",
"bn.js": "^5.2.1",
Expand Down
141 changes: 111 additions & 30 deletions sdk/src/contexts/solana/utils/sendAndConfirmPostVaa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@ import {
} from '@solana/web3.js';
import {
SignTransaction,
sendAndConfirmTransactionsWithRetry,
modifySignTransaction,
TransactionSignatureAndResponse,
PreparedTransactions,
TransactionWithIndex,
sendAndConfirmTransactionsWithRetry,
} from './utils';
import { addComputeBudget } from './computeBudget';
import {
createPostVaaInstruction,
createVerifySignaturesInstructions,
derivePostedVaaKey,
getSignatureSetData,
pendingSignatureVerificationTxs,
} from './wormhole';
import { isBytes, ParsedVaa, parseVaa, SignedVaa } from '../../../vaa/wormhole';

Expand All @@ -33,56 +36,118 @@ export async function postVaaWithRetry(
maxRetries?: number,
commitment?: Commitment,
): Promise<TransactionSignatureAndResponse[]> {
let parsedVaa: ParsedVaa;
try {
// Check if the VAA has already been posted
const parsedVaa = parseVaa(vaa);
parsedVaa = parseVaa(vaa);
const postedVaaAddress = derivePostedVaaKey(
wormholeProgramId,
parsedVaa.hash,
);
const postedVaa = await connection.getAccountInfo(postedVaaAddress);
console.log('postedVaaAddress', postedVaaAddress, postedVaa);
if (postedVaa !== null) {
return [];
}
} catch (e) {
console.error('Failed to check if VAA has already been posted:', e);
}
const set = localStorage.getItem('signatureSet')?.split(',');
const signatureSet =
/*Keypair.generate();*/
Keypair.fromSecretKey(new Uint8Array(set as any));

console.log('signatureSet', signatureSet);
const { unsignedTransactions, signers } =
await createPostSignedVaaTransactions(
connection,
wormholeProgramId,
payer,
vaa,
signatureSet,
commitment,
);
const postVaaTransaction = unsignedTransactions.pop();
if (!postVaaTransaction) throw new Error('No postVaaTransaction');
postVaaTransaction.feePayer = new PublicKey(payer);
postVaaTransaction.transaction.feePayer = new PublicKey(payer);

for (const unsignedTransaction of unsignedTransactions) {
unsignedTransaction.feePayer = new PublicKey(payer);
await addComputeBudget(connection, unsignedTransaction, [], 0.75, 1, true);
}
const responses = await sendAndConfirmTransactionsWithRetry(
// Returns the txs that are NOT present on the blockchain
const transactionsNotPresent = await pendingSignatureVerificationTxs(
unsignedTransactions,
connection,
modifySignTransaction(signTransaction, ...signers),
payer.toString(),
wormholeProgramId,
signatureSet,
commitment,
);

console.log(
'unsignedTransactions & transactionsNotPresent & postVaaTransaction',
unsignedTransactions,
maxRetries,
transactionsNotPresent,
postVaaTransaction,
);

for (const unsignedTransaction of transactionsNotPresent) {
unsignedTransaction.transaction.feePayer = new PublicKey(payer);
await addComputeBudget(
connection,
unsignedTransaction.transaction,
[],
0.75,
1,
true,
);
}

let responses: TransactionSignatureAndResponse[] = [];
if (!!transactionsNotPresent.length) {
responses = await sendAndConfirmTransactionsWithRetry(
connection,
modifySignTransaction(signTransaction, ...signers),
payer.toString(),
transactionsNotPresent.map((tx) => tx.transaction),
{ maxRetries, commitment },
);
// if (responses.errors && responses.errors?.length > 0)
// printError(responses.errors);
}

const signatureSetData1 = await getSignatureSetData(
connection,
signatureSet?.publicKey,
commitment,
);
console.log('signatureSetData1', signatureSetData1);

//While the signature_set is used to create the final instruction, it doesn't need to sign it.
await addComputeBudget(connection, postVaaTransaction, [], 0.75, 1, true);
await addComputeBudget(
connection,
postVaaTransaction.transaction,
[],
0.75,
1,
true,
);
responses.push(
...(await sendAndConfirmTransactionsWithRetry(
connection,
signTransaction,
payer.toString(),
[postVaaTransaction],
maxRetries,
commitment,
[postVaaTransaction.transaction],
{ maxRetries, commitment },
)),
);

const signatureSetData = await getSignatureSetData(
connection,
signatureSet?.publicKey,
commitment,
);
console.log('signatureSetData', signatureSetData);

// if (postVaaResponse.errors && postVaaResponse.errors?.length > 0)
// printError(postVaaResponse.errors);

return responses;
}

Expand All @@ -107,10 +172,10 @@ export async function createPostSignedVaaTransactions(
wormholeProgramId: PublicKeyInitData,
payer: PublicKeyInitData,
vaa: SignedVaa | ParsedVaa,
signatureSet: Keypair,
commitment?: Commitment,
): Promise<PreparedTransactions> {
const parsed = isBytes(vaa) ? parseVaa(vaa) : vaa;
const signatureSet = Keypair.generate();

const verifySignaturesInstructions = await createVerifySignaturesInstructions(
connection,
Expand All @@ -121,27 +186,43 @@ export async function createPostSignedVaaTransactions(
commitment,
);

const unsignedTransactions: Transaction[] = [];
for (let i = 0; i < verifySignaturesInstructions.length; i += 2) {
unsignedTransactions.push(
new Transaction().add(...verifySignaturesInstructions.slice(i, i + 2)),
);
const unsignedTransactions: TransactionWithIndex[] = [];
for (let i = 0; i < verifySignaturesInstructions.length; i++) {
const tx = new Transaction();
tx.add(...verifySignaturesInstructions[i].instructions);

unsignedTransactions.push({
transaction: tx,
index: i,
signatureIndexes: verifySignaturesInstructions[i].signatureIndexes,
});
}

unsignedTransactions.push(
new Transaction().add(
createPostVaaInstruction(
connection,
wormholeProgramId,
payer,
parsed,
signatureSet.publicKey,
),
const postVaaTx = new Transaction();
postVaaTx.add(
createPostVaaInstruction(
connection,
wormholeProgramId,
payer,
parsed,
signatureSet.publicKey,
),
);

unsignedTransactions.push({
transaction: postVaaTx,
index: verifySignaturesInstructions.length,
signatureIndexes: [],
});
return {
unsignedTransactions,
signers: [signatureSet],
};
}

// function printError(errors: any[]) {
// throw new Error(
// 'Error posting VAA to Solana \n' +
// errors.map((error) => error.toString()).join('\n'),
// );
// }
Loading
Loading