Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit 07a83e0

Browse files
authored
feat: add isAccountWritable and isAccountSigner to MessageV0 (#27808)
1 parent b970024 commit 07a83e0

File tree

4 files changed

+174
-8
lines changed

4 files changed

+174
-8
lines changed

web3.js/src/message/legacy.ts

+12-8
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,18 @@ export class Message {
130130
}
131131

132132
isAccountWritable(index: number): boolean {
133-
return (
134-
index <
135-
this.header.numRequiredSignatures -
136-
this.header.numReadonlySignedAccounts ||
137-
(index >= this.header.numRequiredSignatures &&
138-
index <
139-
this.accountKeys.length - this.header.numReadonlyUnsignedAccounts)
140-
);
133+
const numSignedAccounts = this.header.numRequiredSignatures;
134+
if (index >= this.header.numRequiredSignatures) {
135+
const unsignedAccountIndex = index - numSignedAccounts;
136+
const numUnsignedAccounts = this.accountKeys.length - numSignedAccounts;
137+
const numWritableUnsignedAccounts =
138+
numUnsignedAccounts - this.header.numReadonlyUnsignedAccounts;
139+
return unsignedAccountIndex < numWritableUnsignedAccounts;
140+
} else {
141+
const numWritableSignedAccounts =
142+
numSignedAccounts - this.header.numReadonlySignedAccounts;
143+
return index < numWritableSignedAccounts;
144+
}
141145
}
142146

143147
isProgramId(index: number): boolean {

web3.js/src/message/v0.ts

+27
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,33 @@ export class MessageV0 {
103103
);
104104
}
105105

106+
isAccountSigner(index: number): boolean {
107+
return index < this.header.numRequiredSignatures;
108+
}
109+
110+
isAccountWritable(index: number): boolean {
111+
const numSignedAccounts = this.header.numRequiredSignatures;
112+
const numStaticAccountKeys = this.staticAccountKeys.length;
113+
if (index >= numStaticAccountKeys) {
114+
const lookupAccountKeysIndex = index - numStaticAccountKeys;
115+
const numWritableLookupAccountKeys = this.addressTableLookups.reduce(
116+
(count, lookup) => count + lookup.writableIndexes.length,
117+
0,
118+
);
119+
return lookupAccountKeysIndex < numWritableLookupAccountKeys;
120+
} else if (index >= this.header.numRequiredSignatures) {
121+
const unsignedAccountIndex = index - numSignedAccounts;
122+
const numUnsignedAccounts = numStaticAccountKeys - numSignedAccounts;
123+
const numWritableUnsignedAccounts =
124+
numUnsignedAccounts - this.header.numReadonlyUnsignedAccounts;
125+
return unsignedAccountIndex < numWritableUnsignedAccounts;
126+
} else {
127+
const numWritableSignedAccounts =
128+
numSignedAccounts - this.header.numReadonlySignedAccounts;
129+
return index < numWritableSignedAccounts;
130+
}
131+
}
132+
106133
resolveAddressTableLookups(
107134
addressLookupTableAccounts: AddressLookupTableAccount[],
108135
): AccountKeysFromLookups {

web3.js/test/message-tests/legacy.test.ts

+52
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,56 @@ describe('Message', () => {
8888
expect(message.instructions.length).to.eq(0);
8989
expect(message.recentBlockhash).to.eq(recentBlockhash);
9090
});
91+
92+
it('isAccountWritable', () => {
93+
const accountKeys = [
94+
PublicKey.unique(),
95+
PublicKey.unique(),
96+
PublicKey.unique(),
97+
PublicKey.unique(),
98+
];
99+
100+
const recentBlockhash = bs58.encode(sha256('test'));
101+
const message = new Message({
102+
header: {
103+
numRequiredSignatures: 2,
104+
numReadonlySignedAccounts: 1,
105+
numReadonlyUnsignedAccounts: 1,
106+
},
107+
recentBlockhash,
108+
accountKeys,
109+
instructions: [],
110+
});
111+
112+
expect(message.isAccountWritable(0)).to.be.true;
113+
expect(message.isAccountWritable(1)).to.be.false;
114+
expect(message.isAccountWritable(2)).to.be.true;
115+
expect(message.isAccountWritable(3)).to.be.false;
116+
});
117+
118+
it('isAccountSigner', () => {
119+
const accountKeys = [
120+
PublicKey.unique(),
121+
PublicKey.unique(),
122+
PublicKey.unique(),
123+
PublicKey.unique(),
124+
];
125+
126+
const recentBlockhash = bs58.encode(sha256('test'));
127+
const message = new Message({
128+
header: {
129+
numRequiredSignatures: 2,
130+
numReadonlySignedAccounts: 1,
131+
numReadonlyUnsignedAccounts: 1,
132+
},
133+
recentBlockhash,
134+
accountKeys,
135+
instructions: [],
136+
});
137+
138+
expect(message.isAccountSigner(0)).to.be.true;
139+
expect(message.isAccountSigner(1)).to.be.true;
140+
expect(message.isAccountSigner(2)).to.be.false;
141+
expect(message.isAccountSigner(3)).to.be.false;
142+
});
91143
});

web3.js/test/message-tests/v0.test.ts

+83
Original file line numberDiff line numberDiff line change
@@ -298,4 +298,87 @@ describe('MessageV0', () => {
298298
'Expected versioned message with version 0 but found version 1',
299299
);
300300
});
301+
302+
it('isAccountWritable', () => {
303+
const staticAccountKeys = [
304+
PublicKey.unique(),
305+
PublicKey.unique(),
306+
PublicKey.unique(),
307+
PublicKey.unique(),
308+
];
309+
310+
const recentBlockhash = bs58.encode(sha256('test'));
311+
const message = new MessageV0({
312+
header: {
313+
numRequiredSignatures: 2,
314+
numReadonlySignedAccounts: 1,
315+
numReadonlyUnsignedAccounts: 1,
316+
},
317+
recentBlockhash,
318+
staticAccountKeys,
319+
compiledInstructions: [],
320+
addressTableLookups: [
321+
{
322+
accountKey: PublicKey.unique(),
323+
writableIndexes: [0],
324+
readonlyIndexes: [1],
325+
},
326+
{
327+
accountKey: PublicKey.unique(),
328+
writableIndexes: [0],
329+
readonlyIndexes: [1],
330+
},
331+
],
332+
});
333+
334+
expect(message.isAccountWritable(0)).to.be.true;
335+
expect(message.isAccountWritable(1)).to.be.false;
336+
expect(message.isAccountWritable(2)).to.be.true;
337+
expect(message.isAccountWritable(3)).to.be.false;
338+
339+
expect(message.isAccountWritable(4)).to.be.true;
340+
expect(message.isAccountWritable(5)).to.be.true;
341+
342+
expect(message.isAccountWritable(6)).to.be.false;
343+
expect(message.isAccountWritable(7)).to.be.false;
344+
});
345+
346+
it('isAccountSigner', () => {
347+
const staticAccountKeys = [
348+
PublicKey.unique(),
349+
PublicKey.unique(),
350+
PublicKey.unique(),
351+
PublicKey.unique(),
352+
];
353+
354+
const recentBlockhash = bs58.encode(sha256('test'));
355+
const message = new MessageV0({
356+
header: {
357+
numRequiredSignatures: 2,
358+
numReadonlySignedAccounts: 1,
359+
numReadonlyUnsignedAccounts: 1,
360+
},
361+
recentBlockhash,
362+
staticAccountKeys,
363+
compiledInstructions: [],
364+
addressTableLookups: [
365+
{
366+
accountKey: PublicKey.unique(),
367+
writableIndexes: [0],
368+
readonlyIndexes: [1],
369+
},
370+
{
371+
accountKey: PublicKey.unique(),
372+
writableIndexes: [0],
373+
readonlyIndexes: [1],
374+
},
375+
],
376+
});
377+
378+
expect(message.isAccountSigner(0)).to.be.true;
379+
expect(message.isAccountSigner(1)).to.be.true;
380+
for (let i = 2; i < 8; i++) {
381+
expect(message.isAccountSigner(i)).to.be.false;
382+
}
383+
});
301384
});

0 commit comments

Comments
 (0)