forked from solana-labs/solana
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial wasm bindings for
Instruction
, SystemProgram
and `Tra…
…nsaction`
- Loading branch information
Showing
10 changed files
with
272 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ | |
#![cfg(target_arch = "wasm32")] | ||
|
||
pub mod keypair; | ||
pub mod transaction; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
//! `Transaction` Javascript interface | ||
#![cfg(target_arch = "wasm32")] | ||
#![allow(non_snake_case)] | ||
use { | ||
crate::{ | ||
hash::Hash, | ||
signer::keypair::Keypair, | ||
{message::Message, transaction::Transaction}, | ||
}, | ||
solana_program::{ | ||
pubkey::Pubkey, | ||
wasm::{display_to_jsvalue, instructions::Instructions}, | ||
}, | ||
wasm_bindgen::prelude::*, | ||
}; | ||
|
||
#[wasm_bindgen] | ||
impl Transaction { | ||
/// Create a new `Transaction` | ||
#[wasm_bindgen(constructor)] | ||
pub fn constructor(instructions: Instructions, payer: Option<Pubkey>) -> Transaction { | ||
let instructions: Vec<_> = instructions.into(); | ||
Transaction::new_with_payer(&instructions, payer.as_ref()) | ||
} | ||
|
||
/// Return a message containing all data that should be signed. | ||
#[wasm_bindgen(js_name = message)] | ||
pub fn js_message(&self) -> Message { | ||
self.message.clone() | ||
} | ||
|
||
/// Return the serialized message data to sign. | ||
pub fn messageData(&self) -> Box<[u8]> { | ||
self.message_data().into() | ||
} | ||
|
||
/// Verify the transaction | ||
#[wasm_bindgen(js_name = verify)] | ||
pub fn js_verify(&self) -> Result<(), JsValue> { | ||
self.verify().map_err(display_to_jsvalue) | ||
} | ||
|
||
pub fn partialSign(&mut self, keypair: &Keypair, recent_blockhash: &Hash) { | ||
self.partial_sign(&[keypair], *recent_blockhash); | ||
} | ||
|
||
pub fn isSigned(&self) -> bool { | ||
self.is_signed() | ||
} | ||
|
||
pub fn toBytes(&self) -> Box<[u8]> { | ||
bincode::serialize(self).unwrap().into() | ||
} | ||
|
||
pub fn fromBytes(bytes: &[u8]) -> Result<Transaction, JsValue> { | ||
bincode::deserialize(bytes).map_err(display_to_jsvalue) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { expect } from "chai"; | ||
import { | ||
init, | ||
Pubkey, | ||
Keypair, | ||
Hash, | ||
SystemInstruction, | ||
Instructions, | ||
Transaction, | ||
} from "crate"; | ||
init(); | ||
|
||
describe("Transaction", function () { | ||
it("SystemInstruction::Transfer", () => { | ||
const payer = Keypair.fromBytes( | ||
new Uint8Array([ | ||
241, 230, 222, 64, 184, 48, 232, 92, 156, 210, 229, 183, 154, 251, 5, | ||
227, 98, 184, 34, 234, 39, 106, 62, 210, 166, 187, 31, 44, 40, 96, 24, | ||
51, 252, 28, 2, 120, 234, 212, 139, 111, 96, 8, 168, 204, 34, 72, 199, | ||
205, 117, 165, 82, 51, 32, 93, 211, 36, 239, 245, 139, 218, 99, 211, | ||
207, 177, | ||
]) | ||
); | ||
|
||
const src = Keypair.fromBytes( | ||
new Uint8Array([ | ||
172, 219, 139, 103, 154, 105, 92, 23, 227, 108, 174, 80, 215, 227, 62, | ||
8, 66, 38, 151, 239, 148, 184, 180, 148, 149, 18, 106, 94, 73, 143, 27, | ||
132, 193, 64, 199, 93, 222, 83, 172, 224, 116, 205, 54, 38, 191, 178, | ||
149, 71, 65, 132, 46, 71, 126, 81, 63, 254, 21, 101, 90, 52, 67, 204, | ||
128, 199, | ||
]) | ||
); | ||
|
||
const dst = new Pubkey("11111111111111111111111111111112"); | ||
|
||
const recent_blockhash = new Hash( | ||
"EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k" | ||
); | ||
|
||
let instructions = new Instructions(); | ||
instructions.push( | ||
SystemInstruction.transfer(src.pubkey(), dst, BigInt(123)) | ||
); | ||
|
||
let transaction = new Transaction(instructions, payer.pubkey()); | ||
transaction.partialSign(payer, recent_blockhash); | ||
transaction.partialSign(src, recent_blockhash); | ||
expect(transaction.isSigned()).to.be.true; | ||
transaction.verify(); | ||
|
||
expect(Buffer.from(transaction.toBytes()).toString("base64")).to.equal( | ||
"AoZrVzP93eyp3vbl6CU9XQjQfm4Xp/7nSiBlsX/kJmfTQZsGTOrFnt6EUqHVte97fGZ71UAXDfLbR5B31OtRdgdab57BOU8mq0ztMutZAVBPtGJHVly8RPz4TYa+OFU7EIk3Wrv4WUMCb/NR+LxELLH+tQt5SrkvB7rCE2DniM8JAgABBPwcAnjq1ItvYAiozCJIx811pVIzIF3TJO/1i9pj08+xwUDHXd5TrOB0zTYmv7KVR0GELkd+UT/+FWVaNEPMgMcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxJrndgN4IFTxep3s6kO0ROug7bEsbx0xxuDkqEvwUusBAwIBAgwCAAAAewAAAAAAAAA=" | ||
); | ||
}); | ||
}); |