Skip to content

Commit

Permalink
feat: add support for creating version 0 transactions (#27142)
Browse files Browse the repository at this point in the history
* feat: add support for version 0 transactions

* chore: feedback

* chore: update VersionedMessage type

* chore: use literals for version getter

* chore: fix lint error

* chore: switch to VersionedMessage.deserialize
  • Loading branch information
jstarry authored Aug 25, 2022
1 parent 4f2d052 commit 8e30e66
Show file tree
Hide file tree
Showing 11 changed files with 742 additions and 9 deletions.
7 changes: 7 additions & 0 deletions src/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ export const publicKey = (property: string = 'publicKey') => {
return BufferLayout.blob(32, property);
};

/**
* Layout for a signature
*/
export const signature = (property: string = 'signature') => {
return BufferLayout.blob(64, property);
};

/**
* Layout for a 64bit unsigned value
*/
Expand Down
25 changes: 19 additions & 6 deletions src/message/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import {PublicKey} from '../publickey';

export * from './legacy';
export * from './versioned';
export * from './v0';

/**
* The message header, identifying signed and read-only account
Expand All @@ -15,18 +19,27 @@ export type MessageHeader = {
numReadonlyUnsignedAccounts: number;
};

/**
* An address table lookup used to load additional accounts
*/
export type MessageAddressTableLookup = {
accountKey: PublicKey;
writableIndexes: Array<number>;
readonlyIndexes: Array<number>;
};

/**
* An instruction to execute by a program
*
* @property {number} programIdIndex
* @property {number[]} accounts
* @property {string} data
* @property {number[]} accountKeyIndexes
* @property {Uint8Array} data
*/
export type CompiledInstruction = {
export type MessageCompiledInstruction = {
/** Index into the transaction keys array indicating the program account that executes this instruction */
programIdIndex: number;
/** Ordered indices into the transaction keys array indicating which accounts to pass to the program */
accounts: number[];
/** The program input data encoded as base 58 */
data: string;
accountKeyIndexes: number[];
/** The program input data */
data: Uint8Array;
};
55 changes: 53 additions & 2 deletions src/message/legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,30 @@ import * as BufferLayout from '@solana/buffer-layout';
import {PublicKey, PUBLIC_KEY_LENGTH} from '../publickey';
import type {Blockhash} from '../blockhash';
import * as Layout from '../layout';
import {PACKET_DATA_SIZE} from '../transaction/constants';
import {PACKET_DATA_SIZE, VERSION_PREFIX_MASK} from '../transaction/constants';
import * as shortvec from '../utils/shortvec-encoding';
import {toBuffer} from '../utils/to-buffer';
import {CompiledInstruction, MessageHeader} from './index';
import {
MessageHeader,
MessageAddressTableLookup,
MessageCompiledInstruction,
} from './index';

/**
* An instruction to execute by a program
*
* @property {number} programIdIndex
* @property {number[]} accounts
* @property {string} data
*/
export type CompiledInstruction = {
/** Index into the transaction keys array indicating the program account that executes this instruction */
programIdIndex: number;
/** Ordered indices into the transaction keys array indicating which accounts to pass to the program */
accounts: number[];
/** The program input data encoded as base 58 */
data: string;
};

/**
* Message constructor arguments
Expand Down Expand Up @@ -51,6 +71,28 @@ export class Message {
);
}

get version(): 'legacy' {
return 'legacy';
}

get staticAccountKeys(): Array<PublicKey> {
return this.accountKeys;
}

get compiledInstructions(): Array<MessageCompiledInstruction> {
return this.instructions.map(
(ix): MessageCompiledInstruction => ({
programIdIndex: ix.programIdIndex,
accountKeyIndexes: ix.accounts,
data: bs58.decode(ix.data),
}),
);
}

get addressTableLookups(): Array<MessageAddressTableLookup> {
return [];
}

isAccountSigner(index: number): boolean {
return index < this.header.numRequiredSignatures;
}
Expand Down Expand Up @@ -191,6 +233,15 @@ export class Message {
let byteArray = [...buffer];

const numRequiredSignatures = byteArray.shift() as number;
if (
numRequiredSignatures !==
(numRequiredSignatures & VERSION_PREFIX_MASK)
) {
throw new Error(
'Versioned messages must be deserialized with VersionedMessage.deserialize()',
);
}

const numReadonlySignedAccounts = byteArray.shift() as number;
const numReadonlyUnsignedAccounts = byteArray.shift() as number;

Expand Down
Loading

0 comments on commit 8e30e66

Please sign in to comment.