2021-02-01 18:53:24 -08:00
|
|
|
import {Buffer} from 'buffer';
|
2021-07-08 18:01:11 -07:00
|
|
|
import * as BufferLayout from '@solana/buffer-layout';
|
2019-12-23 10:46:49 -08:00
|
|
|
|
|
|
|
import * as Layout from './layout';
|
|
|
|
|
2022-03-23 21:08:10 -07:00
|
|
|
export interface IInstructionInputData {
|
|
|
|
readonly instruction: number;
|
|
|
|
}
|
|
|
|
|
2019-12-23 10:46:49 -08:00
|
|
|
/**
|
2021-03-14 20:01:35 -07:00
|
|
|
* @internal
|
2019-12-23 10:46:49 -08:00
|
|
|
*/
|
2022-03-23 21:08:10 -07:00
|
|
|
export type InstructionType<TInputData extends IInstructionInputData> = {
|
2021-03-31 03:48:41 -07:00
|
|
|
/** The Instruction index (from solana upstream program) */
|
2021-03-14 20:01:35 -07:00
|
|
|
index: number;
|
2021-03-31 03:48:41 -07:00
|
|
|
/** The BufferLayout to use to build data */
|
2022-03-23 21:08:10 -07:00
|
|
|
layout: BufferLayout.Layout<TInputData>;
|
2021-03-14 20:01:35 -07:00
|
|
|
};
|
2019-12-23 10:46:49 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Populate a buffer of instruction data using an InstructionType
|
2021-03-14 20:01:35 -07:00
|
|
|
* @internal
|
2019-12-23 10:46:49 -08:00
|
|
|
*/
|
2022-03-23 21:08:10 -07:00
|
|
|
export function encodeData<TInputData extends IInstructionInputData>(
|
|
|
|
type: InstructionType<TInputData>,
|
|
|
|
fields?: any,
|
|
|
|
): Buffer {
|
2019-12-23 10:46:49 -08:00
|
|
|
const allocLength =
|
|
|
|
type.layout.span >= 0 ? type.layout.span : Layout.getAlloc(type, fields);
|
|
|
|
const data = Buffer.alloc(allocLength);
|
|
|
|
const layoutFields = Object.assign({instruction: type.index}, fields);
|
|
|
|
type.layout.encode(layoutFields, data);
|
|
|
|
return data;
|
|
|
|
}
|
2020-03-02 07:58:10 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Decode instruction data buffer using an InstructionType
|
2021-03-14 20:01:35 -07:00
|
|
|
* @internal
|
2020-03-02 07:58:10 -08:00
|
|
|
*/
|
2022-03-23 21:08:10 -07:00
|
|
|
export function decodeData<TInputData extends IInstructionInputData>(
|
|
|
|
type: InstructionType<TInputData>,
|
|
|
|
buffer: Buffer,
|
|
|
|
): TInputData {
|
|
|
|
let data: TInputData;
|
2020-03-02 07:58:10 -08:00
|
|
|
try {
|
|
|
|
data = type.layout.decode(buffer);
|
|
|
|
} catch (err) {
|
|
|
|
throw new Error('invalid instruction; ' + err);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data.instruction !== type.index) {
|
|
|
|
throw new Error(
|
|
|
|
`invalid instruction; instruction index mismatch ${data.instruction} != ${type.index}`,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|