@metaplex-foundation/umi-transaction-factory-web3js
Version:
A transaction factory implementation relying on Solana's web3.js
101 lines (98 loc) • 4.19 kB
JavaScript
import { SdkError } from '@metaplex-foundation/umi';
import { mapSerializer, struct, array, bytes, shortU16, publicKey, string, base58, u8 } from '@metaplex-foundation/umi/serializers';
import { toWeb3JsMessageFromInput, fromWeb3JsMessage } from '@metaplex-foundation/umi-web3js-adapters';
import { VersionedTransaction } from '@solana/web3.js';
/* eslint-disable no-bitwise */
const TRANSACTION_VERSION_FLAG = 0x80;
const TRANSACTION_VERSION_MASK = 0x7f;
function createWeb3JsTransactionFactory() {
const create = input => {
const web3JsMessage = toWeb3JsMessageFromInput(input);
const message = fromWeb3JsMessage(web3JsMessage);
const web3JsTransaction = new VersionedTransaction(web3JsMessage, input.signatures);
return {
message,
serializedMessage: serializeMessage(message),
signatures: web3JsTransaction.signatures
};
};
const serialize = transaction => getTransactionSerializer().serialize(transaction);
const deserialize = serializedTransaction => getTransactionSerializer().deserialize(serializedTransaction)[0];
const serializeMessage = message => getTransactionMessageSerializer().serialize(message);
const deserializeMessage = serializedMessage => getTransactionMessageSerializer().deserialize(serializedMessage)[0];
const getTransactionSerializer = () => ({
...mapSerializer(struct([['signatures', array(bytes({
size: 64
}), {
size: shortU16()
})], ['serializedMessage', bytes()]]), value => value, value => ({
...value,
message: deserializeMessage(value.serializedMessage)
})),
description: 'Transaction'
});
const getTransactionMessageSerializer = () => ({
description: 'TransactionMessage',
fixedSize: null,
maxSize: null,
serialize: value => {
const serializer = getTransactionMessageSerializerForVersion(value.version);
return serializer.serialize(value);
},
deserialize: (bytes, offset = 0) => {
const [version] = getTransactionVersionSerializer().deserialize(bytes, offset);
const serializer = getTransactionMessageSerializerForVersion(version);
return serializer.deserialize(bytes, offset);
}
});
const getTransactionMessageSerializerForVersion = version => struct([['version', getTransactionVersionSerializer()], ['header', getTransactionMessageHeaderSerializer()], ['accounts', array(publicKey(), {
size: shortU16()
})], ['blockhash', string({
encoding: base58,
size: 32
})], ['instructions', array(getCompiledInstructionSerializer(), {
size: shortU16()
})], ['addressLookupTables', array(getCompiledAddressLookupTableSerializer(), {
size: version === 'legacy' ? 0 : shortU16()
})]]);
const getTransactionVersionSerializer = () => ({
description: 'TransactionVersion',
fixedSize: null,
maxSize: 1,
serialize: value => {
if (value === 'legacy') return new Uint8Array([]);
return new Uint8Array([TRANSACTION_VERSION_FLAG | value]);
},
deserialize: (bytes, offset = 0) => {
const slice = bytes.slice(offset);
if (slice.length === 0 || (slice[0] & TRANSACTION_VERSION_FLAG) === 0) {
return ['legacy', offset];
}
const version = slice[0] & TRANSACTION_VERSION_MASK;
if (version > 0) {
throw new SdkError(`Unsupported transaction version: ${version}.`);
}
return [version, offset + 1];
}
});
const getTransactionMessageHeaderSerializer = () => struct([['numRequiredSignatures', u8()], ['numReadonlySignedAccounts', u8()], ['numReadonlyUnsignedAccounts', u8()]]);
const getCompiledInstructionSerializer = () => struct([['programIndex', u8()], ['accountIndexes', array(u8(), {
size: shortU16()
})], ['data', bytes({
size: shortU16()
})]]);
const getCompiledAddressLookupTableSerializer = () => struct([['publicKey', publicKey()], ['writableIndexes', array(u8(), {
size: shortU16()
})], ['readonlyIndexes', array(u8(), {
size: shortU16()
})]]);
return {
create,
serialize,
deserialize,
serializeMessage,
deserializeMessage
};
}
export { createWeb3JsTransactionFactory };
//# sourceMappingURL=createWeb3JsTransactionFactory.mjs.map