Add initial wasm bindings for Instruction, SystemProgram and Transaction

This commit is contained in:
Michael Vines
2021-10-18 08:39:21 -07:00
parent 03a956e8d9
commit a35df1cb02
10 changed files with 272 additions and 4 deletions

View File

@ -2,7 +2,7 @@
//! Defines a composable Instruction type and a memory-efficient CompiledInstruction.
use {
crate::{pubkey::Pubkey, sanitize::Sanitize, short_vec},
crate::{pubkey::Pubkey, sanitize::Sanitize, short_vec, wasm_bindgen},
bincode::serialize,
borsh::BorshSerialize,
serde::Serialize,
@ -240,13 +240,17 @@ pub enum InstructionError {
// conversions must also be added
}
#[wasm_bindgen]
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct Instruction {
/// Pubkey of the instruction processor that executes this instruction
#[wasm_bindgen(skip)]
pub program_id: Pubkey,
/// Metadata for what accounts should be passed to the instruction processor
#[wasm_bindgen(skip)]
pub accounts: Vec<AccountMeta>,
/// Opaque data passed to the instruction processor
#[wasm_bindgen(skip)]
pub data: Vec<u8>,
}

View File

@ -12,7 +12,7 @@ use {
serialize_utils::{
append_slice, append_u16, append_u8, read_pubkey, read_slice, read_u16, read_u8,
},
short_vec, system_instruction, system_program, sysvar,
short_vec, system_instruction, system_program, sysvar, wasm_bindgen,
},
lazy_static::lazy_static,
std::{collections::BTreeSet, convert::TryFrom, str::FromStr},
@ -168,15 +168,18 @@ fn get_program_ids(instructions: &[Instruction]) -> Vec<Pubkey> {
// NOTE: Serialization-related changes must be paired with the custom serialization
// for versioned messages in the `RemainingLegacyMessage` struct.
#[wasm_bindgen]
#[frozen_abi(digest = "2KnLEqfLcTBQqitE22Pp8JYkaqVVbAkGbCfdeHoyxcAU")]
#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone, AbiExample)]
#[serde(rename_all = "camelCase")]
pub struct Message {
/// The message header, identifying signed and read-only `account_keys`
/// NOTE: Serialization-related changes must be paired with the direct read at sigverify.
#[wasm_bindgen(skip)]
pub header: MessageHeader,
/// All the account keys used by this transaction
#[wasm_bindgen(skip)]
#[serde(with = "short_vec")]
pub account_keys: Vec<Pubkey>,
@ -185,6 +188,7 @@ pub struct Message {
/// Programs that will be executed in sequence and committed in one atomic transaction if all
/// succeed.
#[wasm_bindgen(skip)]
#[serde(with = "short_vec")]
pub instructions: Vec<CompiledInstruction>,
}

View File

@ -1,5 +1,4 @@
#[allow(deprecated)]
use crate::sysvar::recent_blockhashes;
use {
crate::{
decode_error::DecodeError,
@ -7,7 +6,7 @@ use {
nonce,
pubkey::Pubkey,
system_program,
sysvar::rent,
sysvar::{recent_blockhashes, rent},
},
num_derive::{FromPrimitive, ToPrimitive},
thiserror::Error,

View File

@ -0,0 +1,28 @@
//! The `Instructions` struct is a workaround for the lack of Vec<T> support in wasm-bindgen
//! (ref: https://github.com/rustwasm/wasm-bindgen/issues/111)
#![cfg(target_arch = "wasm32")]
use {crate::instruction::Instruction, wasm_bindgen::prelude::*};
#[wasm_bindgen]
#[derive(Default)]
pub struct Instructions {
instructions: Vec<Instruction>,
}
#[wasm_bindgen]
impl Instructions {
#[wasm_bindgen(constructor)]
pub fn constructor() -> Instructions {
Instructions::default()
}
pub fn push(&mut self, instruction: Instruction) {
self.instructions.push(instruction);
}
}
impl From<Instructions> for Vec<Instruction> {
fn from(instructions: Instructions) -> Self {
instructions.instructions
}
}

View File

@ -3,7 +3,9 @@
use wasm_bindgen::prelude::*;
pub mod hash;
pub mod instructions;
pub mod pubkey;
pub mod system_instruction;
/// Initialize Javascript logging and panic handler
#[wasm_bindgen]

View File

@ -0,0 +1,112 @@
//! `SystemInstruction` Javascript interface
#![cfg(target_arch = "wasm32")]
#![allow(non_snake_case)]
use {
crate::{instruction::Instruction, pubkey::Pubkey, system_instruction::*},
wasm_bindgen::prelude::*,
};
#[wasm_bindgen]
impl SystemInstruction {
pub fn createAccount(
from_pubkey: &Pubkey,
to_pubkey: &Pubkey,
lamports: u64,
space: u64,
owner: &Pubkey,
) -> Instruction {
create_account(from_pubkey, to_pubkey, lamports, space, owner)
}
pub fn createAccountWithSeed(
from_pubkey: &Pubkey,
to_pubkey: &Pubkey,
base: &Pubkey,
seed: &str,
lamports: u64,
space: u64,
owner: &Pubkey,
) -> Instruction {
create_account_with_seed(from_pubkey, to_pubkey, base, seed, lamports, space, owner)
}
pub fn assign(pubkey: &Pubkey, owner: &Pubkey) -> Instruction {
assign(pubkey, owner)
}
pub fn assignWithSeed(
pubkey: &Pubkey,
base: &Pubkey,
seed: &str,
owner: &Pubkey,
) -> Instruction {
assign_with_seed(pubkey, base, seed, owner)
}
pub fn transfer(from_pubkey: &Pubkey, to_pubkey: &Pubkey, lamports: u64) -> Instruction {
transfer(from_pubkey, to_pubkey, lamports)
}
pub fn transferWithSeed(
from_pubkey: &Pubkey,
from_base: &Pubkey,
from_seed: String,
from_owner: &Pubkey,
to_pubkey: &Pubkey,
lamports: u64,
) -> Instruction {
transfer_with_seed(
from_pubkey,
from_base,
from_seed,
from_owner,
to_pubkey,
lamports,
)
}
pub fn allocate(pubkey: &Pubkey, space: u64) -> Instruction {
allocate(pubkey, space)
}
pub fn allocateWithSeed(
address: &Pubkey,
base: &Pubkey,
seed: &str,
space: u64,
owner: &Pubkey,
) -> Instruction {
allocate_with_seed(address, base, seed, space, owner)
}
pub fn createNonceAccount(
from_pubkey: &Pubkey,
nonce_pubkey: &Pubkey,
authority: &Pubkey,
lamports: u64,
) -> js_sys::Array {
let instructions = create_nonce_account(from_pubkey, nonce_pubkey, authority, lamports);
instructions.into_iter().map(JsValue::from).collect()
}
pub fn advanceNonceAccount(nonce_pubkey: &Pubkey, authorized_pubkey: &Pubkey) -> Instruction {
advance_nonce_account(nonce_pubkey, authorized_pubkey)
}
pub fn withdrawNonceAccount(
nonce_pubkey: &Pubkey,
authorized_pubkey: &Pubkey,
to_pubkey: &Pubkey,
lamports: u64,
) -> Instruction {
withdraw_nonce_account(nonce_pubkey, authorized_pubkey, to_pubkey, lamports)
}
pub fn authorizeNonceAccount(
nonce_pubkey: &Pubkey,
authorized_pubkey: &Pubkey,
new_authority: &Pubkey,
) -> Instruction {
authorize_nonce_account(nonce_pubkey, authorized_pubkey, new_authority)
}
}