@solana/transaction-messages
Advanced tools
Comparing version 2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2 to 2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685
@@ -1,4 +0,4 @@ | ||
import { SolanaError, SOLANA_ERROR__TRANSACTION__EXPECTED_BLOCKHASH_LIFETIME, SOLANA_ERROR__TRANSACTION__VERSION_NUMBER_OUT_OF_RANGE, SOLANA_ERROR__TRANSACTION__EXPECTED_NONCE_LIFETIME, SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE, SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_CANNOT_PAY_FEES } from '@solana/errors'; | ||
import { SolanaError, SOLANA_ERROR__TRANSACTION__EXPECTED_BLOCKHASH_LIFETIME, SOLANA_ERROR__TRANSACTION__VERSION_NUMBER_OUT_OF_RANGE, SOLANA_ERROR__TRANSACTION__EXPECTED_NONCE_LIFETIME, SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_FEE_PAYER_MISSING, SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE, SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_CANNOT_PAY_FEES, SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_CONTENTS_MISSING, SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_INDEX_OUT_OF_RANGE, SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_INSTRUCTION_PROGRAM_ADDRESS_NOT_FOUND } from '@solana/errors'; | ||
import { assertIsBlockhash } from '@solana/rpc-types'; | ||
import { getAddressEncoder, getAddressDecoder, getAddressComparator } from '@solana/addresses'; | ||
import { getAddressEncoder, getAddressDecoder, getAddressComparator, assertIsAddress } from '@solana/addresses'; | ||
import { combineCodec, transformEncoder, addEncoderSizePrefix, transformDecoder, addDecoderSizePrefix, createEncoder, createDecoder } from '@solana/codecs-core'; | ||
@@ -8,2 +8,3 @@ import { getStructEncoder, getArrayEncoder, getStructDecoder, getArrayDecoder, getStructCodec, getBytesEncoder, getBytesDecoder } from '@solana/codecs-data-structures'; | ||
import { AccountRole, isSignerRole, isWritableRole, mergeRoles } from '@solana/instructions'; | ||
import { pipe } from '@solana/functional'; | ||
@@ -596,4 +597,145 @@ // src/blockhash.ts | ||
export { ADDRESS_MAP_TYPE_PROPERTY, AddressMapEntryType, appendTransactionMessageInstruction, appendTransactionMessageInstructions, assertIsDurableNonceTransactionMessage, assertIsTransactionMessageWithBlockhashLifetime, createTransactionMessage, getAddressMapFromInstructions, getAddressTableLookupCodec, getAddressTableLookupDecoder, getAddressTableLookupEncoder, getCompiledAddressTableLookups, getCompiledInstructions, getCompiledLifetimeToken, getCompiledMessageHeader, getCompiledStaticAccounts, getInstructionCodec, getInstructionDecoder, getInstructionEncoder, getMessageHeaderCodec, getMessageHeaderDecoder, getMessageHeaderEncoder, getOrderedAccountsFromAddressMap, getTransactionVersionCodec, getTransactionVersionDecoder, getTransactionVersionEncoder, newCompileTransactionMessage, newIsAdvanceNonceAccountInstruction, prependTransactionMessageInstruction, prependTransactionMessageInstructions, setTransactionMessageFeePayer, setTransactionMessageLifetimeUsingBlockhash, setTransactionMessageLifetimeUsingDurableNonce }; | ||
// src/decompile-message.ts | ||
function getAccountMetas(message) { | ||
const { header } = message; | ||
const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts; | ||
const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts; | ||
const accountMetas = []; | ||
let accountIndex = 0; | ||
for (let i = 0; i < numWritableSignerAccounts; i++) { | ||
accountMetas.push({ | ||
address: message.staticAccounts[accountIndex], | ||
role: AccountRole.WRITABLE_SIGNER | ||
}); | ||
accountIndex++; | ||
} | ||
for (let i = 0; i < header.numReadonlySignerAccounts; i++) { | ||
accountMetas.push({ | ||
address: message.staticAccounts[accountIndex], | ||
role: AccountRole.READONLY_SIGNER | ||
}); | ||
accountIndex++; | ||
} | ||
for (let i = 0; i < numWritableNonSignerAccounts; i++) { | ||
accountMetas.push({ | ||
address: message.staticAccounts[accountIndex], | ||
role: AccountRole.WRITABLE | ||
}); | ||
accountIndex++; | ||
} | ||
for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) { | ||
accountMetas.push({ | ||
address: message.staticAccounts[accountIndex], | ||
role: AccountRole.READONLY | ||
}); | ||
accountIndex++; | ||
} | ||
return accountMetas; | ||
} | ||
function getAddressLookupMetas(compiledAddressTableLookups, addressesByLookupTableAddress) { | ||
const compiledAddressTableLookupAddresses = compiledAddressTableLookups.map((l) => l.lookupTableAddress); | ||
const missing = compiledAddressTableLookupAddresses.filter((a) => addressesByLookupTableAddress[a] === void 0); | ||
if (missing.length > 0) { | ||
throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_CONTENTS_MISSING, { | ||
lookupTableAddresses: missing | ||
}); | ||
} | ||
const readOnlyMetas = []; | ||
const writableMetas = []; | ||
for (const lookup of compiledAddressTableLookups) { | ||
const addresses = addressesByLookupTableAddress[lookup.lookupTableAddress]; | ||
const highestIndex = Math.max(...lookup.readableIndices, ...lookup.writableIndices); | ||
if (highestIndex >= addresses.length) { | ||
throw new SolanaError( | ||
SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_INDEX_OUT_OF_RANGE, | ||
{ | ||
highestKnownIndex: addresses.length - 1, | ||
highestRequestedIndex: highestIndex, | ||
lookupTableAddress: lookup.lookupTableAddress | ||
} | ||
); | ||
} | ||
const readOnlyForLookup = lookup.readableIndices.map((r) => ({ | ||
address: addresses[r], | ||
addressIndex: r, | ||
lookupTableAddress: lookup.lookupTableAddress, | ||
role: AccountRole.READONLY | ||
})); | ||
readOnlyMetas.push(...readOnlyForLookup); | ||
const writableForLookup = lookup.writableIndices.map((w) => ({ | ||
address: addresses[w], | ||
addressIndex: w, | ||
lookupTableAddress: lookup.lookupTableAddress, | ||
role: AccountRole.WRITABLE | ||
})); | ||
writableMetas.push(...writableForLookup); | ||
} | ||
return [...writableMetas, ...readOnlyMetas]; | ||
} | ||
function convertInstruction(instruction, accountMetas) { | ||
const programAddress = accountMetas[instruction.programAddressIndex]?.address; | ||
if (!programAddress) { | ||
throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_INSTRUCTION_PROGRAM_ADDRESS_NOT_FOUND, { | ||
index: instruction.programAddressIndex | ||
}); | ||
} | ||
const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]); | ||
const { data } = instruction; | ||
return { | ||
programAddress, | ||
...accounts && accounts.length ? { accounts } : {}, | ||
...data && data.length ? { data } : {} | ||
}; | ||
} | ||
function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) { | ||
if (!firstInstruction || !newIsAdvanceNonceAccountInstruction(firstInstruction)) { | ||
return { | ||
blockhash: messageLifetimeToken, | ||
lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n | ||
// U64 MAX | ||
}; | ||
} else { | ||
const nonceAccountAddress = firstInstruction.accounts[0].address; | ||
assertIsAddress(nonceAccountAddress); | ||
const nonceAuthorityAddress = firstInstruction.accounts[2].address; | ||
assertIsAddress(nonceAuthorityAddress); | ||
return { | ||
nonce: messageLifetimeToken, | ||
nonceAccountAddress, | ||
nonceAuthorityAddress | ||
}; | ||
} | ||
} | ||
function decompileTransactionMessage(compiledTransactionMessage, config) { | ||
const feePayer = compiledTransactionMessage.staticAccounts[0]; | ||
if (!feePayer) { | ||
throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_FEE_PAYER_MISSING); | ||
} | ||
const accountMetas = getAccountMetas(compiledTransactionMessage); | ||
const accountLookupMetas = "addressTableLookups" in compiledTransactionMessage && compiledTransactionMessage.addressTableLookups !== void 0 && compiledTransactionMessage.addressTableLookups.length > 0 ? getAddressLookupMetas( | ||
compiledTransactionMessage.addressTableLookups, | ||
config?.addressesByLookupTableAddress ?? {} | ||
) : []; | ||
const transactionMetas = [...accountMetas, ...accountLookupMetas]; | ||
const instructions = compiledTransactionMessage.instructions.map( | ||
(compiledInstruction) => convertInstruction(compiledInstruction, transactionMetas) | ||
); | ||
const firstInstruction = instructions[0]; | ||
const lifetimeConstraint = getLifetimeConstraint( | ||
compiledTransactionMessage.lifetimeToken, | ||
firstInstruction, | ||
config?.lastValidBlockHeight | ||
); | ||
return pipe( | ||
createTransactionMessage({ version: compiledTransactionMessage.version }), | ||
(tx) => setTransactionMessageFeePayer(feePayer, tx), | ||
(tx) => instructions.reduce((acc, instruction) => { | ||
return appendTransactionMessageInstruction(instruction, acc); | ||
}, tx), | ||
(tx) => "blockhash" in lifetimeConstraint ? setTransactionMessageLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionMessageLifetimeUsingDurableNonce(lifetimeConstraint, tx) | ||
); | ||
} | ||
export { ADDRESS_MAP_TYPE_PROPERTY, AddressMapEntryType, appendTransactionMessageInstruction, appendTransactionMessageInstructions, assertIsDurableNonceTransactionMessage, assertIsTransactionMessageWithBlockhashLifetime, createTransactionMessage, decompileTransactionMessage, getAddressMapFromInstructions, getAddressTableLookupCodec, getAddressTableLookupDecoder, getAddressTableLookupEncoder, getCompiledAddressTableLookups, getCompiledInstructions, getCompiledLifetimeToken, getCompiledMessageHeader, getCompiledStaticAccounts, getInstructionCodec, getInstructionDecoder, getInstructionEncoder, getMessageHeaderCodec, getMessageHeaderDecoder, getMessageHeaderEncoder, getOrderedAccountsFromAddressMap, getTransactionVersionCodec, getTransactionVersionDecoder, getTransactionVersionEncoder, newCompileTransactionMessage, newIsAdvanceNonceAccountInstruction, prependTransactionMessageInstruction, prependTransactionMessageInstructions, setTransactionMessageFeePayer, setTransactionMessageLifetimeUsingBlockhash, setTransactionMessageLifetimeUsingDurableNonce }; | ||
//# sourceMappingURL=out.js.map | ||
//# sourceMappingURL=index.browser.js.map |
@@ -1,4 +0,4 @@ | ||
import { SolanaError, SOLANA_ERROR__TRANSACTION__EXPECTED_BLOCKHASH_LIFETIME, SOLANA_ERROR__TRANSACTION__VERSION_NUMBER_OUT_OF_RANGE, SOLANA_ERROR__TRANSACTION__EXPECTED_NONCE_LIFETIME, SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE, SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_CANNOT_PAY_FEES } from '@solana/errors'; | ||
import { SolanaError, SOLANA_ERROR__TRANSACTION__EXPECTED_BLOCKHASH_LIFETIME, SOLANA_ERROR__TRANSACTION__VERSION_NUMBER_OUT_OF_RANGE, SOLANA_ERROR__TRANSACTION__EXPECTED_NONCE_LIFETIME, SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_FEE_PAYER_MISSING, SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE, SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_CANNOT_PAY_FEES, SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_CONTENTS_MISSING, SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_INDEX_OUT_OF_RANGE, SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_INSTRUCTION_PROGRAM_ADDRESS_NOT_FOUND } from '@solana/errors'; | ||
import { assertIsBlockhash } from '@solana/rpc-types'; | ||
import { getAddressEncoder, getAddressDecoder, getAddressComparator } from '@solana/addresses'; | ||
import { getAddressEncoder, getAddressDecoder, getAddressComparator, assertIsAddress } from '@solana/addresses'; | ||
import { combineCodec, transformEncoder, addEncoderSizePrefix, transformDecoder, addDecoderSizePrefix, createEncoder, createDecoder } from '@solana/codecs-core'; | ||
@@ -8,2 +8,3 @@ import { getStructEncoder, getArrayEncoder, getStructDecoder, getArrayDecoder, getStructCodec, getBytesEncoder, getBytesDecoder } from '@solana/codecs-data-structures'; | ||
import { AccountRole, isSignerRole, isWritableRole, mergeRoles } from '@solana/instructions'; | ||
import { pipe } from '@solana/functional'; | ||
@@ -596,4 +597,145 @@ // src/blockhash.ts | ||
export { ADDRESS_MAP_TYPE_PROPERTY, AddressMapEntryType, appendTransactionMessageInstruction, appendTransactionMessageInstructions, assertIsDurableNonceTransactionMessage, assertIsTransactionMessageWithBlockhashLifetime, createTransactionMessage, getAddressMapFromInstructions, getAddressTableLookupCodec, getAddressTableLookupDecoder, getAddressTableLookupEncoder, getCompiledAddressTableLookups, getCompiledInstructions, getCompiledLifetimeToken, getCompiledMessageHeader, getCompiledStaticAccounts, getInstructionCodec, getInstructionDecoder, getInstructionEncoder, getMessageHeaderCodec, getMessageHeaderDecoder, getMessageHeaderEncoder, getOrderedAccountsFromAddressMap, getTransactionVersionCodec, getTransactionVersionDecoder, getTransactionVersionEncoder, newCompileTransactionMessage, newIsAdvanceNonceAccountInstruction, prependTransactionMessageInstruction, prependTransactionMessageInstructions, setTransactionMessageFeePayer, setTransactionMessageLifetimeUsingBlockhash, setTransactionMessageLifetimeUsingDurableNonce }; | ||
// src/decompile-message.ts | ||
function getAccountMetas(message) { | ||
const { header } = message; | ||
const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts; | ||
const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts; | ||
const accountMetas = []; | ||
let accountIndex = 0; | ||
for (let i = 0; i < numWritableSignerAccounts; i++) { | ||
accountMetas.push({ | ||
address: message.staticAccounts[accountIndex], | ||
role: AccountRole.WRITABLE_SIGNER | ||
}); | ||
accountIndex++; | ||
} | ||
for (let i = 0; i < header.numReadonlySignerAccounts; i++) { | ||
accountMetas.push({ | ||
address: message.staticAccounts[accountIndex], | ||
role: AccountRole.READONLY_SIGNER | ||
}); | ||
accountIndex++; | ||
} | ||
for (let i = 0; i < numWritableNonSignerAccounts; i++) { | ||
accountMetas.push({ | ||
address: message.staticAccounts[accountIndex], | ||
role: AccountRole.WRITABLE | ||
}); | ||
accountIndex++; | ||
} | ||
for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) { | ||
accountMetas.push({ | ||
address: message.staticAccounts[accountIndex], | ||
role: AccountRole.READONLY | ||
}); | ||
accountIndex++; | ||
} | ||
return accountMetas; | ||
} | ||
function getAddressLookupMetas(compiledAddressTableLookups, addressesByLookupTableAddress) { | ||
const compiledAddressTableLookupAddresses = compiledAddressTableLookups.map((l) => l.lookupTableAddress); | ||
const missing = compiledAddressTableLookupAddresses.filter((a) => addressesByLookupTableAddress[a] === void 0); | ||
if (missing.length > 0) { | ||
throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_CONTENTS_MISSING, { | ||
lookupTableAddresses: missing | ||
}); | ||
} | ||
const readOnlyMetas = []; | ||
const writableMetas = []; | ||
for (const lookup of compiledAddressTableLookups) { | ||
const addresses = addressesByLookupTableAddress[lookup.lookupTableAddress]; | ||
const highestIndex = Math.max(...lookup.readableIndices, ...lookup.writableIndices); | ||
if (highestIndex >= addresses.length) { | ||
throw new SolanaError( | ||
SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_INDEX_OUT_OF_RANGE, | ||
{ | ||
highestKnownIndex: addresses.length - 1, | ||
highestRequestedIndex: highestIndex, | ||
lookupTableAddress: lookup.lookupTableAddress | ||
} | ||
); | ||
} | ||
const readOnlyForLookup = lookup.readableIndices.map((r) => ({ | ||
address: addresses[r], | ||
addressIndex: r, | ||
lookupTableAddress: lookup.lookupTableAddress, | ||
role: AccountRole.READONLY | ||
})); | ||
readOnlyMetas.push(...readOnlyForLookup); | ||
const writableForLookup = lookup.writableIndices.map((w) => ({ | ||
address: addresses[w], | ||
addressIndex: w, | ||
lookupTableAddress: lookup.lookupTableAddress, | ||
role: AccountRole.WRITABLE | ||
})); | ||
writableMetas.push(...writableForLookup); | ||
} | ||
return [...writableMetas, ...readOnlyMetas]; | ||
} | ||
function convertInstruction(instruction, accountMetas) { | ||
const programAddress = accountMetas[instruction.programAddressIndex]?.address; | ||
if (!programAddress) { | ||
throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_INSTRUCTION_PROGRAM_ADDRESS_NOT_FOUND, { | ||
index: instruction.programAddressIndex | ||
}); | ||
} | ||
const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]); | ||
const { data } = instruction; | ||
return { | ||
programAddress, | ||
...accounts && accounts.length ? { accounts } : {}, | ||
...data && data.length ? { data } : {} | ||
}; | ||
} | ||
function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) { | ||
if (!firstInstruction || !newIsAdvanceNonceAccountInstruction(firstInstruction)) { | ||
return { | ||
blockhash: messageLifetimeToken, | ||
lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n | ||
// U64 MAX | ||
}; | ||
} else { | ||
const nonceAccountAddress = firstInstruction.accounts[0].address; | ||
assertIsAddress(nonceAccountAddress); | ||
const nonceAuthorityAddress = firstInstruction.accounts[2].address; | ||
assertIsAddress(nonceAuthorityAddress); | ||
return { | ||
nonce: messageLifetimeToken, | ||
nonceAccountAddress, | ||
nonceAuthorityAddress | ||
}; | ||
} | ||
} | ||
function decompileTransactionMessage(compiledTransactionMessage, config) { | ||
const feePayer = compiledTransactionMessage.staticAccounts[0]; | ||
if (!feePayer) { | ||
throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_FEE_PAYER_MISSING); | ||
} | ||
const accountMetas = getAccountMetas(compiledTransactionMessage); | ||
const accountLookupMetas = "addressTableLookups" in compiledTransactionMessage && compiledTransactionMessage.addressTableLookups !== void 0 && compiledTransactionMessage.addressTableLookups.length > 0 ? getAddressLookupMetas( | ||
compiledTransactionMessage.addressTableLookups, | ||
config?.addressesByLookupTableAddress ?? {} | ||
) : []; | ||
const transactionMetas = [...accountMetas, ...accountLookupMetas]; | ||
const instructions = compiledTransactionMessage.instructions.map( | ||
(compiledInstruction) => convertInstruction(compiledInstruction, transactionMetas) | ||
); | ||
const firstInstruction = instructions[0]; | ||
const lifetimeConstraint = getLifetimeConstraint( | ||
compiledTransactionMessage.lifetimeToken, | ||
firstInstruction, | ||
config?.lastValidBlockHeight | ||
); | ||
return pipe( | ||
createTransactionMessage({ version: compiledTransactionMessage.version }), | ||
(tx) => setTransactionMessageFeePayer(feePayer, tx), | ||
(tx) => instructions.reduce((acc, instruction) => { | ||
return appendTransactionMessageInstruction(instruction, acc); | ||
}, tx), | ||
(tx) => "blockhash" in lifetimeConstraint ? setTransactionMessageLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionMessageLifetimeUsingDurableNonce(lifetimeConstraint, tx) | ||
); | ||
} | ||
export { ADDRESS_MAP_TYPE_PROPERTY, AddressMapEntryType, appendTransactionMessageInstruction, appendTransactionMessageInstructions, assertIsDurableNonceTransactionMessage, assertIsTransactionMessageWithBlockhashLifetime, createTransactionMessage, decompileTransactionMessage, getAddressMapFromInstructions, getAddressTableLookupCodec, getAddressTableLookupDecoder, getAddressTableLookupEncoder, getCompiledAddressTableLookups, getCompiledInstructions, getCompiledLifetimeToken, getCompiledMessageHeader, getCompiledStaticAccounts, getInstructionCodec, getInstructionDecoder, getInstructionEncoder, getMessageHeaderCodec, getMessageHeaderDecoder, getMessageHeaderEncoder, getOrderedAccountsFromAddressMap, getTransactionVersionCodec, getTransactionVersionDecoder, getTransactionVersionEncoder, newCompileTransactionMessage, newIsAdvanceNonceAccountInstruction, prependTransactionMessageInstruction, prependTransactionMessageInstructions, setTransactionMessageFeePayer, setTransactionMessageLifetimeUsingBlockhash, setTransactionMessageLifetimeUsingDurableNonce }; | ||
//# sourceMappingURL=out.js.map | ||
//# sourceMappingURL=index.native.js.map |
@@ -1,4 +0,4 @@ | ||
import { SolanaError, SOLANA_ERROR__TRANSACTION__EXPECTED_BLOCKHASH_LIFETIME, SOLANA_ERROR__TRANSACTION__VERSION_NUMBER_OUT_OF_RANGE, SOLANA_ERROR__TRANSACTION__EXPECTED_NONCE_LIFETIME, SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE, SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_CANNOT_PAY_FEES } from '@solana/errors'; | ||
import { SolanaError, SOLANA_ERROR__TRANSACTION__EXPECTED_BLOCKHASH_LIFETIME, SOLANA_ERROR__TRANSACTION__VERSION_NUMBER_OUT_OF_RANGE, SOLANA_ERROR__TRANSACTION__EXPECTED_NONCE_LIFETIME, SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_FEE_PAYER_MISSING, SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE, SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_CANNOT_PAY_FEES, SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_CONTENTS_MISSING, SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_INDEX_OUT_OF_RANGE, SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_INSTRUCTION_PROGRAM_ADDRESS_NOT_FOUND } from '@solana/errors'; | ||
import { assertIsBlockhash } from '@solana/rpc-types'; | ||
import { getAddressEncoder, getAddressDecoder, getAddressComparator } from '@solana/addresses'; | ||
import { getAddressEncoder, getAddressDecoder, getAddressComparator, assertIsAddress } from '@solana/addresses'; | ||
import { combineCodec, transformEncoder, addEncoderSizePrefix, transformDecoder, addDecoderSizePrefix, createEncoder, createDecoder } from '@solana/codecs-core'; | ||
@@ -8,2 +8,3 @@ import { getStructEncoder, getArrayEncoder, getStructDecoder, getArrayDecoder, getStructCodec, getBytesEncoder, getBytesDecoder } from '@solana/codecs-data-structures'; | ||
import { AccountRole, isSignerRole, isWritableRole, mergeRoles } from '@solana/instructions'; | ||
import { pipe } from '@solana/functional'; | ||
@@ -596,4 +597,145 @@ // src/blockhash.ts | ||
export { ADDRESS_MAP_TYPE_PROPERTY, AddressMapEntryType, appendTransactionMessageInstruction, appendTransactionMessageInstructions, assertIsDurableNonceTransactionMessage, assertIsTransactionMessageWithBlockhashLifetime, createTransactionMessage, getAddressMapFromInstructions, getAddressTableLookupCodec, getAddressTableLookupDecoder, getAddressTableLookupEncoder, getCompiledAddressTableLookups, getCompiledInstructions, getCompiledLifetimeToken, getCompiledMessageHeader, getCompiledStaticAccounts, getInstructionCodec, getInstructionDecoder, getInstructionEncoder, getMessageHeaderCodec, getMessageHeaderDecoder, getMessageHeaderEncoder, getOrderedAccountsFromAddressMap, getTransactionVersionCodec, getTransactionVersionDecoder, getTransactionVersionEncoder, newCompileTransactionMessage, newIsAdvanceNonceAccountInstruction, prependTransactionMessageInstruction, prependTransactionMessageInstructions, setTransactionMessageFeePayer, setTransactionMessageLifetimeUsingBlockhash, setTransactionMessageLifetimeUsingDurableNonce }; | ||
// src/decompile-message.ts | ||
function getAccountMetas(message) { | ||
const { header } = message; | ||
const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts; | ||
const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts; | ||
const accountMetas = []; | ||
let accountIndex = 0; | ||
for (let i = 0; i < numWritableSignerAccounts; i++) { | ||
accountMetas.push({ | ||
address: message.staticAccounts[accountIndex], | ||
role: AccountRole.WRITABLE_SIGNER | ||
}); | ||
accountIndex++; | ||
} | ||
for (let i = 0; i < header.numReadonlySignerAccounts; i++) { | ||
accountMetas.push({ | ||
address: message.staticAccounts[accountIndex], | ||
role: AccountRole.READONLY_SIGNER | ||
}); | ||
accountIndex++; | ||
} | ||
for (let i = 0; i < numWritableNonSignerAccounts; i++) { | ||
accountMetas.push({ | ||
address: message.staticAccounts[accountIndex], | ||
role: AccountRole.WRITABLE | ||
}); | ||
accountIndex++; | ||
} | ||
for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) { | ||
accountMetas.push({ | ||
address: message.staticAccounts[accountIndex], | ||
role: AccountRole.READONLY | ||
}); | ||
accountIndex++; | ||
} | ||
return accountMetas; | ||
} | ||
function getAddressLookupMetas(compiledAddressTableLookups, addressesByLookupTableAddress) { | ||
const compiledAddressTableLookupAddresses = compiledAddressTableLookups.map((l) => l.lookupTableAddress); | ||
const missing = compiledAddressTableLookupAddresses.filter((a) => addressesByLookupTableAddress[a] === void 0); | ||
if (missing.length > 0) { | ||
throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_CONTENTS_MISSING, { | ||
lookupTableAddresses: missing | ||
}); | ||
} | ||
const readOnlyMetas = []; | ||
const writableMetas = []; | ||
for (const lookup of compiledAddressTableLookups) { | ||
const addresses = addressesByLookupTableAddress[lookup.lookupTableAddress]; | ||
const highestIndex = Math.max(...lookup.readableIndices, ...lookup.writableIndices); | ||
if (highestIndex >= addresses.length) { | ||
throw new SolanaError( | ||
SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_INDEX_OUT_OF_RANGE, | ||
{ | ||
highestKnownIndex: addresses.length - 1, | ||
highestRequestedIndex: highestIndex, | ||
lookupTableAddress: lookup.lookupTableAddress | ||
} | ||
); | ||
} | ||
const readOnlyForLookup = lookup.readableIndices.map((r) => ({ | ||
address: addresses[r], | ||
addressIndex: r, | ||
lookupTableAddress: lookup.lookupTableAddress, | ||
role: AccountRole.READONLY | ||
})); | ||
readOnlyMetas.push(...readOnlyForLookup); | ||
const writableForLookup = lookup.writableIndices.map((w) => ({ | ||
address: addresses[w], | ||
addressIndex: w, | ||
lookupTableAddress: lookup.lookupTableAddress, | ||
role: AccountRole.WRITABLE | ||
})); | ||
writableMetas.push(...writableForLookup); | ||
} | ||
return [...writableMetas, ...readOnlyMetas]; | ||
} | ||
function convertInstruction(instruction, accountMetas) { | ||
const programAddress = accountMetas[instruction.programAddressIndex]?.address; | ||
if (!programAddress) { | ||
throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_INSTRUCTION_PROGRAM_ADDRESS_NOT_FOUND, { | ||
index: instruction.programAddressIndex | ||
}); | ||
} | ||
const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]); | ||
const { data } = instruction; | ||
return { | ||
programAddress, | ||
...accounts && accounts.length ? { accounts } : {}, | ||
...data && data.length ? { data } : {} | ||
}; | ||
} | ||
function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) { | ||
if (!firstInstruction || !newIsAdvanceNonceAccountInstruction(firstInstruction)) { | ||
return { | ||
blockhash: messageLifetimeToken, | ||
lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n | ||
// U64 MAX | ||
}; | ||
} else { | ||
const nonceAccountAddress = firstInstruction.accounts[0].address; | ||
assertIsAddress(nonceAccountAddress); | ||
const nonceAuthorityAddress = firstInstruction.accounts[2].address; | ||
assertIsAddress(nonceAuthorityAddress); | ||
return { | ||
nonce: messageLifetimeToken, | ||
nonceAccountAddress, | ||
nonceAuthorityAddress | ||
}; | ||
} | ||
} | ||
function decompileTransactionMessage(compiledTransactionMessage, config) { | ||
const feePayer = compiledTransactionMessage.staticAccounts[0]; | ||
if (!feePayer) { | ||
throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_FEE_PAYER_MISSING); | ||
} | ||
const accountMetas = getAccountMetas(compiledTransactionMessage); | ||
const accountLookupMetas = "addressTableLookups" in compiledTransactionMessage && compiledTransactionMessage.addressTableLookups !== void 0 && compiledTransactionMessage.addressTableLookups.length > 0 ? getAddressLookupMetas( | ||
compiledTransactionMessage.addressTableLookups, | ||
config?.addressesByLookupTableAddress ?? {} | ||
) : []; | ||
const transactionMetas = [...accountMetas, ...accountLookupMetas]; | ||
const instructions = compiledTransactionMessage.instructions.map( | ||
(compiledInstruction) => convertInstruction(compiledInstruction, transactionMetas) | ||
); | ||
const firstInstruction = instructions[0]; | ||
const lifetimeConstraint = getLifetimeConstraint( | ||
compiledTransactionMessage.lifetimeToken, | ||
firstInstruction, | ||
config?.lastValidBlockHeight | ||
); | ||
return pipe( | ||
createTransactionMessage({ version: compiledTransactionMessage.version }), | ||
(tx) => setTransactionMessageFeePayer(feePayer, tx), | ||
(tx) => instructions.reduce((acc, instruction) => { | ||
return appendTransactionMessageInstruction(instruction, acc); | ||
}, tx), | ||
(tx) => "blockhash" in lifetimeConstraint ? setTransactionMessageLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionMessageLifetimeUsingDurableNonce(lifetimeConstraint, tx) | ||
); | ||
} | ||
export { ADDRESS_MAP_TYPE_PROPERTY, AddressMapEntryType, appendTransactionMessageInstruction, appendTransactionMessageInstructions, assertIsDurableNonceTransactionMessage, assertIsTransactionMessageWithBlockhashLifetime, createTransactionMessage, decompileTransactionMessage, getAddressMapFromInstructions, getAddressTableLookupCodec, getAddressTableLookupDecoder, getAddressTableLookupEncoder, getCompiledAddressTableLookups, getCompiledInstructions, getCompiledLifetimeToken, getCompiledMessageHeader, getCompiledStaticAccounts, getInstructionCodec, getInstructionDecoder, getInstructionEncoder, getMessageHeaderCodec, getMessageHeaderDecoder, getMessageHeaderEncoder, getOrderedAccountsFromAddressMap, getTransactionVersionCodec, getTransactionVersionDecoder, getTransactionVersionEncoder, newCompileTransactionMessage, newIsAdvanceNonceAccountInstruction, prependTransactionMessageInstruction, prependTransactionMessageInstructions, setTransactionMessageFeePayer, setTransactionMessageLifetimeUsingBlockhash, setTransactionMessageLifetimeUsingDurableNonce }; | ||
//# sourceMappingURL=out.js.map | ||
//# sourceMappingURL=index.node.js.map |
@@ -5,2 +5,3 @@ export * from './blockhash.js'; | ||
export * from './create-transaction-message.js'; | ||
export * from './decompile-message.js'; | ||
export * from './durable-nonce.js'; | ||
@@ -7,0 +8,0 @@ export * from './fee-payer.js'; |
{ | ||
"name": "@solana/transaction-messages", | ||
"version": "2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2", | ||
"version": "2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685", | ||
"description": "Helpers for creating transaction messages", | ||
@@ -49,9 +49,10 @@ "exports": { | ||
"dependencies": { | ||
"@solana/addresses": "2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2", | ||
"@solana/codecs-core": "2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2", | ||
"@solana/codecs-data-structures": "2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2", | ||
"@solana/codecs-numbers": "2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2", | ||
"@solana/errors": "2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2", | ||
"@solana/instructions": "2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2", | ||
"@solana/rpc-types": "2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2" | ||
"@solana/addresses": "2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685", | ||
"@solana/codecs-core": "2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685", | ||
"@solana/codecs-data-structures": "2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685", | ||
"@solana/codecs-numbers": "2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685", | ||
"@solana/functional": "2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685", | ||
"@solana/errors": "2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685", | ||
"@solana/instructions": "2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685", | ||
"@solana/rpc-types": "2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685" | ||
}, | ||
@@ -58,0 +59,0 @@ "bundlewatch": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
532268
57
3955
8
+ Added@solana/functional@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685
+ Added@solana/addresses@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685(transitive)
+ Added@solana/assertions@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685(transitive)
+ Added@solana/codecs-core@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685(transitive)
+ Added@solana/codecs-data-structures@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685(transitive)
+ Added@solana/codecs-numbers@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685(transitive)
+ Added@solana/codecs-strings@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685(transitive)
+ Added@solana/errors@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685(transitive)
+ Added@solana/functional@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685(transitive)
+ Added@solana/instructions@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685(transitive)
+ Added@solana/rpc-types@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685(transitive)
- Removed@solana/addresses@2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2(transitive)
- Removed@solana/assertions@2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2(transitive)
- Removed@solana/codecs-core@2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2(transitive)
- Removed@solana/codecs-data-structures@2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2(transitive)
- Removed@solana/codecs-numbers@2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2(transitive)
- Removed@solana/codecs-strings@2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2(transitive)
- Removed@solana/errors@2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2(transitive)
- Removed@solana/instructions@2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2(transitive)
- Removed@solana/rpc-types@2.0.0-preview.1.20240410070917.be788e38f0138cdbe71ebb5d8ed866025f369ef2(transitive)
Updated@solana/addresses@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685
Updated@solana/codecs-core@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685
Updated@solana/codecs-numbers@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685
Updated@solana/errors@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685
Updated@solana/instructions@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685
Updated@solana/rpc-types@2.0.0-preview.1.20240410071201.f060e526775b212b42271902de59f8ab25392685