Skip to content

Commit

Permalink
fix: sort accountMetas after deduping
Browse files Browse the repository at this point in the history
  • Loading branch information
sudhir-b authored and steveluscher committed May 30, 2022
1 parent 4b1dd0f commit 20f169c
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 11 deletions.
24 changes: 13 additions & 11 deletions web3.js/src/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,17 +376,6 @@ export class Transaction {
});
});

// Sort. Prioritizing first by signer, then by writable
accountMetas.sort(function (x, y) {
const pubkeySorting = x.pubkey
.toBase58()
.localeCompare(y.pubkey.toBase58());
const checkSigner = x.isSigner === y.isSigner ? 0 : x.isSigner ? -1 : 1;
const checkWritable =
x.isWritable === y.isWritable ? pubkeySorting : x.isWritable ? -1 : 1;
return checkSigner || checkWritable;
});

// Cull duplicate account metas
const uniqueMetas: AccountMeta[] = [];
accountMetas.forEach(accountMeta => {
Expand All @@ -397,11 +386,24 @@ export class Transaction {
if (uniqueIndex > -1) {
uniqueMetas[uniqueIndex].isWritable =
uniqueMetas[uniqueIndex].isWritable || accountMeta.isWritable;
uniqueMetas[uniqueIndex].isSigner =
uniqueMetas[uniqueIndex].isSigner || accountMeta.isSigner;
} else {
uniqueMetas.push(accountMeta);
}
});

// Sort. Prioritizing first by signer, then by writable
uniqueMetas.sort(function (x, y) {
const pubkeySorting = x.pubkey
.toBase58()
.localeCompare(y.pubkey.toBase58());
const checkSigner = x.isSigner === y.isSigner ? 0 : x.isSigner ? -1 : 1;
const checkWritable =
x.isWritable === y.isWritable ? pubkeySorting : x.isWritable ? -1 : 1;
return checkSigner || checkWritable;
});

// Move fee payer to the front
const feePayerIndex = uniqueMetas.findIndex(x => {
return x.pubkey.equals(feePayer);
Expand Down
27 changes: 27 additions & 0 deletions web3.js/test/transaction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,33 @@ describe('Transaction', () => {
expect(message.accountKeys[2]).to.eql(account3.publicKey);
});

it('accountKeys are sorted & deduplicated correctly', () => {
const payer = Keypair.generate();
const account2 = new PublicKey(2);
const account3 = new PublicKey(1);
const recentBlockhash = Keypair.generate().publicKey.toBase58();
const programId = Keypair.generate().publicKey;
const transaction = new Transaction({
blockhash: recentBlockhash,
lastValidBlockHeight: 9999,
}).add({
keys: [
{pubkey: account3, isSigner: true, isWritable: false},
{pubkey: payer.publicKey, isSigner: true, isWritable: true},
{pubkey: account2, isSigner: false, isWritable: true},
{pubkey: account2, isSigner: true, isWritable: false},
],
programId,
});

transaction.feePayer = payer.publicKey;

const message = transaction.compileMessage();
expect(message.accountKeys[0]).to.eql(payer.publicKey);
expect(message.accountKeys[1].toBase58()).to.eql(account2.toBase58());
expect(message.accountKeys[2].toBase58()).to.eql(account3.toBase58());
});

it('payer is first account meta', () => {
const payer = Keypair.generate();
const other = Keypair.generate();
Expand Down

0 comments on commit 20f169c

Please sign in to comment.