|
1 | 1 | 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'; |
3 | 3 | import { TransactionInstruction } from '@solana/web3.js';
|
4 | 4 | import { programSupportsExtensions, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from '../../constants.js';
|
5 | 5 | import { TokenUnsupportedInstructionError } from '../../errors.js';
|
@@ -117,6 +117,25 @@ export function createUpdateTransferHookInstruction(
|
117 | 117 | return new TransactionInstruction({ keys, programId, data });
|
118 | 118 | }
|
119 | 119 |
|
| 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 | + |
120 | 139 | /**
|
121 | 140 | * Add extra accounts needed for transfer hook to an instruction
|
122 | 141 | *
|
@@ -156,13 +175,14 @@ export async function addExtraAccountsToInstruction(
|
156 | 175 | accountMetas.push({ pubkey: extraAccountsAccount, isSigner: false, isWritable: false });
|
157 | 176 |
|
158 | 177 | for (const extraAccountMeta of extraAccountMetas) {
|
159 |
| - const accountMeta = await resolveExtraAccountMeta( |
| 178 | + const accountMetaUnchecked = await resolveExtraAccountMeta( |
160 | 179 | connection,
|
161 | 180 | extraAccountMeta,
|
162 | 181 | accountMetas,
|
163 | 182 | instruction.data,
|
164 | 183 | transferHook.programId
|
165 | 184 | );
|
| 185 | + const accountMeta = deEscalateAccountMeta(accountMetaUnchecked, accountMetas); |
166 | 186 | accountMetas.push(accountMeta);
|
167 | 187 | }
|
168 | 188 | accountMetas.push({ pubkey: transferHook.programId, isSigner: false, isWritable: false });
|
|
0 commit comments