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

Commit 1b89c06

Browse files
author
Joe C
authored
[token js]: transfer-hook: add account meta de-escalation
This PR adds the `deEscalateAccountMeta` function in JavaScript, which was previously missing. The new function operates exactly the same as its Rust counterpart in `spl-tlv-account-resolution`. Addresses point number 1 in #5686.
1 parent 7b3fef1 commit 1b89c06

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

token/js/src/extensions/transferHook/instructions.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { struct, u8 } from '@solana/buffer-layout';
2-
import type { Commitment, Connection, PublicKey, Signer } from '@solana/web3.js';
2+
import type { AccountMeta, Commitment, Connection, PublicKey, Signer } from '@solana/web3.js';
33
import { TransactionInstruction } from '@solana/web3.js';
44
import { programSupportsExtensions, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from '../../constants.js';
55
import { TokenUnsupportedInstructionError } from '../../errors.js';
@@ -117,6 +117,25 @@ export function createUpdateTransferHookInstruction(
117117
return new TransactionInstruction({ keys, programId, data });
118118
}
119119

120+
function deEscalateAccountMeta(accountMeta: AccountMeta, accountMetas: AccountMeta[]): AccountMeta {
121+
const maybeHighestPrivileges = accountMetas
122+
.filter((x) => x.pubkey === accountMeta.pubkey)
123+
.reduce<{ isSigner: boolean; isWritable: boolean } | undefined>((acc, x) => {
124+
if (!acc) return { isSigner: x.isSigner, isWritable: x.isWritable };
125+
return { isSigner: acc.isSigner || x.isSigner, isWritable: acc.isWritable || x.isWritable };
126+
}, undefined);
127+
if (maybeHighestPrivileges) {
128+
const { isSigner, isWritable } = maybeHighestPrivileges;
129+
if (!isSigner && isSigner !== accountMeta.isSigner) {
130+
accountMeta.isSigner = false;
131+
}
132+
if (!isWritable && isWritable !== accountMeta.isWritable) {
133+
accountMeta.isWritable = false;
134+
}
135+
}
136+
return accountMeta;
137+
}
138+
120139
/**
121140
* Add extra accounts needed for transfer hook to an instruction
122141
*
@@ -156,13 +175,14 @@ export async function addExtraAccountsToInstruction(
156175
accountMetas.push({ pubkey: extraAccountsAccount, isSigner: false, isWritable: false });
157176

158177
for (const extraAccountMeta of extraAccountMetas) {
159-
const accountMeta = await resolveExtraAccountMeta(
178+
const accountMetaUnchecked = await resolveExtraAccountMeta(
160179
connection,
161180
extraAccountMeta,
162181
accountMetas,
163182
instruction.data,
164183
transferHook.programId
165184
);
185+
const accountMeta = deEscalateAccountMeta(accountMetaUnchecked, accountMetas);
166186
accountMetas.push(accountMeta);
167187
}
168188
accountMetas.push({ pubkey: transferHook.programId, isSigner: false, isWritable: false });

0 commit comments

Comments
 (0)