Implement WASM client for token bridge
Change-Id: I592cc0ece0553d55c50d87010783fefb7f9b5f2f
This commit is contained in:
parent
f9eb8a2c0a
commit
dfdf31dcce
|
@ -10,6 +10,11 @@ set -euo pipefail
|
|||
-v $(pwd)/../bridge_ui/rust_modules/core:/usr/src/bridge/bridge/program/pkg \
|
||||
-e EMITTER_ADDRESS=11111111111111111111111111111115 \
|
||||
localhost/certusone/wormhole-wasmpack:latest \
|
||||
/usr/local/cargo/bin/wasm-pack build --target nodejs -- --features no-entrypoint
|
||||
/usr/local/cargo/bin/wasm-pack build --target nodejs -- --features wasm
|
||||
cp $(pwd)/../bridge_ui/rust_modules/core/. $(pwd)/../clients/solana/pkg/ -R
|
||||
docker run --rm -it --workdir /usr/src/bridge/modules/token_bridge/program \
|
||||
-v $(pwd)/../bridge_ui/rust_modules/token:/usr/src/bridge/modules/token_bridge/program/pkg \
|
||||
-e EMITTER_ADDRESS=11111111111111111111111111111115 \
|
||||
localhost/certusone/wormhole-wasmpack:latest \
|
||||
/usr/local/cargo/bin/wasm-pack build --target nodejs -- --features wasm
|
||||
)
|
||||
|
|
|
@ -12,6 +12,7 @@ name = "bridge"
|
|||
client = ["solitaire/client", "solitaire-client", "no-entrypoint"]
|
||||
cpi = ["no-entrypoint"]
|
||||
default = []
|
||||
wasm = ["no-entrypoint"]
|
||||
no-entrypoint = ["solitaire/no-entrypoint"]
|
||||
trace = ["solitaire/trace"]
|
||||
|
||||
|
|
|
@ -42,6 +42,10 @@ use std::io::{
|
|||
Cursor,
|
||||
Write,
|
||||
};
|
||||
use serde::{
|
||||
Deserialize,
|
||||
Serialize
|
||||
};
|
||||
|
||||
impl From<&PostVAAData> for GuardianSetDerivationData {
|
||||
fn from(data: &PostVAAData) -> Self {
|
||||
|
@ -88,7 +92,7 @@ pub struct Signature {
|
|||
|
||||
pub type ForeignAddress = [u8; 32];
|
||||
|
||||
#[derive(Default, BorshSerialize, BorshDeserialize, Clone)]
|
||||
#[derive(Default, BorshSerialize, BorshDeserialize, Clone, Serialize, Deserialize)]
|
||||
pub struct PostVAAData {
|
||||
// Header part
|
||||
pub version: u8,
|
||||
|
|
|
@ -11,9 +11,11 @@ pub mod vaa;
|
|||
#[cfg(feature = "no-entrypoint")]
|
||||
pub mod instructions;
|
||||
|
||||
#[cfg(feature = "wasm")]
|
||||
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
|
||||
extern crate wasm_bindgen;
|
||||
|
||||
#[cfg(feature = "wasm")]
|
||||
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
|
||||
pub mod wasm;
|
||||
|
||||
|
|
|
@ -1502,8 +1502,6 @@ checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
|
|||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
[workspace]
|
||||
members = ["program"]
|
||||
|
||||
[patch.crates-io]
|
||||
memmap2 = { path = "../../bridge/memmap2-rs" }
|
|
@ -11,6 +11,7 @@ name = "token_bridge"
|
|||
[features]
|
||||
no-entrypoint = ["solitaire/no-entrypoint", "rand"]
|
||||
trace = ["solitaire/trace"]
|
||||
wasm = ["no-entrypoint"]
|
||||
client = ["solitaire-client", "solitaire/client", "no-entrypoint"]
|
||||
cpi = ["no-entrypoint"]
|
||||
default = []
|
||||
|
|
|
@ -58,15 +58,17 @@ use bridge::{
|
|||
CHAIN_ID_SOLANA,
|
||||
};
|
||||
use primitive_types::U256;
|
||||
use solana_program::instruction::Instruction;
|
||||
use solana_program::{
|
||||
instruction::{
|
||||
AccountMeta,
|
||||
Instruction,
|
||||
},
|
||||
pubkey::Pubkey,
|
||||
};
|
||||
use solitaire::{
|
||||
processors::seeded::Seeded,
|
||||
AccountState,
|
||||
};
|
||||
use solana_program::instruction::{
|
||||
AccountMeta,
|
||||
};
|
||||
use solana_program::pubkey::Pubkey;
|
||||
use spl_token::state::Mint;
|
||||
use std::str::FromStr;
|
||||
|
||||
|
|
|
@ -6,6 +6,14 @@
|
|||
#[cfg(feature = "no-entrypoint")]
|
||||
pub mod instructions;
|
||||
|
||||
#[cfg(feature = "wasm")]
|
||||
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
|
||||
extern crate wasm_bindgen;
|
||||
|
||||
#[cfg(feature = "wasm")]
|
||||
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
|
||||
pub mod wasm;
|
||||
|
||||
pub mod accounts;
|
||||
pub mod api;
|
||||
pub mod messages;
|
||||
|
@ -20,6 +28,7 @@ pub use api::{
|
|||
register_chain,
|
||||
transfer_native,
|
||||
transfer_wrapped,
|
||||
upgrade_contract,
|
||||
AttestToken,
|
||||
AttestTokenData,
|
||||
CompleteNative,
|
||||
|
@ -38,7 +47,6 @@ pub use api::{
|
|||
TransferWrappedData,
|
||||
UpgradeContract,
|
||||
UpgradeContractData,
|
||||
upgrade_contract
|
||||
};
|
||||
|
||||
use solitaire::*;
|
||||
|
|
|
@ -0,0 +1,374 @@
|
|||
use crate::{
|
||||
instructions::{
|
||||
attest,
|
||||
complete_native,
|
||||
complete_wrapped,
|
||||
create_wrapped,
|
||||
register_chain,
|
||||
transfer_native,
|
||||
transfer_wrapped,
|
||||
upgrade_contract,
|
||||
},
|
||||
messages::{
|
||||
GovernancePayloadUpgrade,
|
||||
PayloadAssetMeta,
|
||||
PayloadGovernanceRegisterChain,
|
||||
PayloadTransfer,
|
||||
},
|
||||
CompleteNativeData,
|
||||
CompleteWrappedData,
|
||||
CreateWrappedData,
|
||||
RegisterChainData,
|
||||
TransferNativeData,
|
||||
TransferWrappedData,
|
||||
};
|
||||
use bridge::{
|
||||
accounts::MessageDerivationData,
|
||||
vaa::VAA,
|
||||
DeserializePayload,
|
||||
PostVAAData,
|
||||
};
|
||||
use solana_program::pubkey::Pubkey;
|
||||
use solitaire::{
|
||||
processors::seeded::Seeded,
|
||||
AccountState,
|
||||
};
|
||||
use std::str::FromStr;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn attest_ix(
|
||||
program_id: String,
|
||||
bridge_id: String,
|
||||
payer: String,
|
||||
mint: String,
|
||||
decimals: u8,
|
||||
mint_meta: String,
|
||||
nonce: u32,
|
||||
) -> JsValue {
|
||||
let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
|
||||
let bridge_id = Pubkey::from_str(bridge_id.as_str()).unwrap();
|
||||
let payer = Pubkey::from_str(payer.as_str()).unwrap();
|
||||
let mint = Pubkey::from_str(mint.as_str()).unwrap();
|
||||
let mint_meta = Pubkey::from_str(mint_meta.as_str()).unwrap();
|
||||
|
||||
let ix = attest(
|
||||
program_id, bridge_id, payer, mint, decimals, mint_meta, nonce,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
JsValue::from_serde(&ix).unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn transfer_native_ix(
|
||||
program_id: String,
|
||||
bridge_id: String,
|
||||
payer: String,
|
||||
from: String,
|
||||
mint: String,
|
||||
nonce: u32,
|
||||
amount: u64,
|
||||
fee: u64,
|
||||
target_address: Vec<u8>,
|
||||
target_chain: u16,
|
||||
) -> JsValue {
|
||||
let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
|
||||
let bridge_id = Pubkey::from_str(bridge_id.as_str()).unwrap();
|
||||
let payer = Pubkey::from_str(payer.as_str()).unwrap();
|
||||
let from = Pubkey::from_str(from.as_str()).unwrap();
|
||||
let mint = Pubkey::from_str(mint.as_str()).unwrap();
|
||||
|
||||
let mut target_addr = [0u8; 32];
|
||||
target_addr.copy_from_slice(target_address.as_slice());
|
||||
|
||||
let ix = transfer_native(
|
||||
program_id,
|
||||
bridge_id,
|
||||
payer,
|
||||
from,
|
||||
mint,
|
||||
TransferNativeData {
|
||||
nonce,
|
||||
amount,
|
||||
fee,
|
||||
target_address: target_addr,
|
||||
target_chain,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
JsValue::from_serde(&ix).unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn transfer_wrapped_ix(
|
||||
program_id: String,
|
||||
bridge_id: String,
|
||||
payer: String,
|
||||
from: String,
|
||||
from_owner: String,
|
||||
token_chain: u16,
|
||||
token_address: Vec<u8>,
|
||||
nonce: u32,
|
||||
amount: u64,
|
||||
fee: u64,
|
||||
target_address: Vec<u8>,
|
||||
target_chain: u16,
|
||||
) -> JsValue {
|
||||
let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
|
||||
let bridge_id = Pubkey::from_str(bridge_id.as_str()).unwrap();
|
||||
let payer = Pubkey::from_str(payer.as_str()).unwrap();
|
||||
let from = Pubkey::from_str(from.as_str()).unwrap();
|
||||
let from_owner = Pubkey::from_str(from_owner.as_str()).unwrap();
|
||||
|
||||
let mut target_addr = [0u8; 32];
|
||||
target_addr.copy_from_slice(target_address.as_slice());
|
||||
let mut token_addr = [0u8; 32];
|
||||
token_addr.copy_from_slice(token_address.as_slice());
|
||||
|
||||
let ix = transfer_wrapped(
|
||||
program_id,
|
||||
bridge_id,
|
||||
payer,
|
||||
from,
|
||||
from_owner,
|
||||
token_chain,
|
||||
token_addr,
|
||||
TransferWrappedData {
|
||||
nonce,
|
||||
amount,
|
||||
fee,
|
||||
target_address: target_addr,
|
||||
target_chain,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
JsValue::from_serde(&ix).unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn complete_transfer_native_ix(
|
||||
program_id: String,
|
||||
bridge_id: String,
|
||||
payer: String,
|
||||
vaa: Vec<u8>,
|
||||
) -> JsValue {
|
||||
let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
|
||||
let bridge_id = Pubkey::from_str(bridge_id.as_str()).unwrap();
|
||||
let payer = Pubkey::from_str(payer.as_str()).unwrap();
|
||||
let vaa = VAA::deserialize(vaa.as_slice()).unwrap();
|
||||
let payload = PayloadTransfer::deserialize(&mut vaa.payload.as_slice()).unwrap();
|
||||
let message_key = bridge::accounts::Message::<'_, { AccountState::Uninitialized }>::key(
|
||||
&MessageDerivationData {
|
||||
emitter_key: vaa.emitter_address,
|
||||
emitter_chain: vaa.emitter_chain,
|
||||
nonce: vaa.nonce,
|
||||
payload: vaa.payload.clone(),
|
||||
sequence: None,
|
||||
},
|
||||
&program_id,
|
||||
);
|
||||
let post_vaa_data = PostVAAData {
|
||||
version: vaa.version,
|
||||
guardian_set_index: vaa.guardian_set_index,
|
||||
timestamp: vaa.timestamp,
|
||||
nonce: vaa.nonce,
|
||||
emitter_chain: vaa.emitter_chain,
|
||||
emitter_address: vaa.emitter_address,
|
||||
sequence: vaa.sequence,
|
||||
consistency_level: vaa.consistency_level,
|
||||
payload: vaa.payload,
|
||||
};
|
||||
|
||||
let ix = complete_native(
|
||||
program_id,
|
||||
bridge_id,
|
||||
payer,
|
||||
message_key,
|
||||
post_vaa_data,
|
||||
Pubkey::new(&payload.to[..]),
|
||||
Pubkey::new(&payload.token_address),
|
||||
CompleteNativeData {},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
JsValue::from_serde(&ix).unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn complete_transfer_wrapped_ix(
|
||||
program_id: String,
|
||||
bridge_id: String,
|
||||
payer: String,
|
||||
vaa: Vec<u8>,
|
||||
) -> JsValue {
|
||||
let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
|
||||
let bridge_id = Pubkey::from_str(bridge_id.as_str()).unwrap();
|
||||
let payer = Pubkey::from_str(payer.as_str()).unwrap();
|
||||
let vaa = VAA::deserialize(vaa.as_slice()).unwrap();
|
||||
let payload = PayloadTransfer::deserialize(&mut vaa.payload.as_slice()).unwrap();
|
||||
let message_key = bridge::accounts::Message::<'_, { AccountState::Uninitialized }>::key(
|
||||
&MessageDerivationData {
|
||||
emitter_key: vaa.emitter_address,
|
||||
emitter_chain: vaa.emitter_chain,
|
||||
nonce: vaa.nonce,
|
||||
payload: vaa.payload.clone(),
|
||||
sequence: None,
|
||||
},
|
||||
&program_id,
|
||||
);
|
||||
let post_vaa_data = PostVAAData {
|
||||
version: vaa.version,
|
||||
guardian_set_index: vaa.guardian_set_index,
|
||||
timestamp: vaa.timestamp,
|
||||
nonce: vaa.nonce,
|
||||
emitter_chain: vaa.emitter_chain,
|
||||
emitter_address: vaa.emitter_address,
|
||||
sequence: vaa.sequence,
|
||||
consistency_level: vaa.consistency_level,
|
||||
payload: vaa.payload,
|
||||
};
|
||||
|
||||
let ix = complete_wrapped(
|
||||
program_id,
|
||||
bridge_id,
|
||||
payer,
|
||||
message_key,
|
||||
post_vaa_data,
|
||||
payload.clone(),
|
||||
Pubkey::new(&payload.to),
|
||||
CompleteWrappedData {},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
JsValue::from_serde(&ix).unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn create_wrapped_ix(
|
||||
program_id: String,
|
||||
bridge_id: String,
|
||||
payer: String,
|
||||
vaa: Vec<u8>,
|
||||
) -> JsValue {
|
||||
let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
|
||||
let bridge_id = Pubkey::from_str(bridge_id.as_str()).unwrap();
|
||||
let payer = Pubkey::from_str(payer.as_str()).unwrap();
|
||||
let vaa = VAA::deserialize(vaa.as_slice()).unwrap();
|
||||
let payload = PayloadAssetMeta::deserialize(&mut vaa.payload.as_slice()).unwrap();
|
||||
let message_key = bridge::accounts::Message::<'_, { AccountState::Uninitialized }>::key(
|
||||
&MessageDerivationData {
|
||||
emitter_key: vaa.emitter_address,
|
||||
emitter_chain: vaa.emitter_chain,
|
||||
nonce: vaa.nonce,
|
||||
payload: vaa.payload.clone(),
|
||||
sequence: None,
|
||||
},
|
||||
&program_id,
|
||||
);
|
||||
let post_vaa_data = PostVAAData {
|
||||
version: vaa.version,
|
||||
guardian_set_index: vaa.guardian_set_index,
|
||||
timestamp: vaa.timestamp,
|
||||
nonce: vaa.nonce,
|
||||
emitter_chain: vaa.emitter_chain,
|
||||
emitter_address: vaa.emitter_address,
|
||||
sequence: vaa.sequence,
|
||||
consistency_level: vaa.consistency_level,
|
||||
payload: vaa.payload,
|
||||
};
|
||||
|
||||
let ix = create_wrapped(
|
||||
program_id,
|
||||
bridge_id,
|
||||
payer,
|
||||
message_key,
|
||||
post_vaa_data,
|
||||
payload,
|
||||
CreateWrappedData {},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
JsValue::from_serde(&ix).unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn upgrade_contract_ix(
|
||||
program_id: String,
|
||||
payer: String,
|
||||
spill: String,
|
||||
vaa: Vec<u8>,
|
||||
) -> JsValue {
|
||||
let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
|
||||
let spill = Pubkey::from_str(spill.as_str()).unwrap();
|
||||
let vaa = VAA::deserialize(vaa.as_slice()).unwrap();
|
||||
let payload = GovernancePayloadUpgrade::deserialize(&mut vaa.payload.as_slice()).unwrap();
|
||||
let message_key = bridge::accounts::Message::<'_, { AccountState::Uninitialized }>::key(
|
||||
&MessageDerivationData {
|
||||
emitter_key: vaa.emitter_address,
|
||||
emitter_chain: vaa.emitter_chain,
|
||||
nonce: vaa.nonce,
|
||||
payload: vaa.payload,
|
||||
sequence: None,
|
||||
},
|
||||
&program_id,
|
||||
);
|
||||
let ix = upgrade_contract(
|
||||
program_id,
|
||||
Pubkey::from_str(payer.as_str()).unwrap(),
|
||||
message_key,
|
||||
Pubkey::new(&vaa.emitter_address),
|
||||
payload.new_contract,
|
||||
spill,
|
||||
vaa.sequence,
|
||||
);
|
||||
return JsValue::from_serde(&ix).unwrap();
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn register_chain_ix(
|
||||
program_id: String,
|
||||
bridge_id: String,
|
||||
payer: String,
|
||||
vaa: Vec<u8>,
|
||||
) -> JsValue {
|
||||
let program_id = Pubkey::from_str(program_id.as_str()).unwrap();
|
||||
let bridge_id = Pubkey::from_str(bridge_id.as_str()).unwrap();
|
||||
let payer = Pubkey::from_str(payer.as_str()).unwrap();
|
||||
let vaa = VAA::deserialize(vaa.as_slice()).unwrap();
|
||||
let payload = PayloadGovernanceRegisterChain::deserialize(&mut vaa.payload.as_slice()).unwrap();
|
||||
let message_key = bridge::accounts::Message::<'_, { AccountState::Uninitialized }>::key(
|
||||
&MessageDerivationData {
|
||||
emitter_key: vaa.emitter_address,
|
||||
emitter_chain: vaa.emitter_chain,
|
||||
nonce: vaa.nonce,
|
||||
payload: vaa.payload.clone(),
|
||||
sequence: None,
|
||||
},
|
||||
&program_id,
|
||||
);
|
||||
let post_vaa_data = PostVAAData {
|
||||
version: vaa.version,
|
||||
guardian_set_index: vaa.guardian_set_index,
|
||||
timestamp: vaa.timestamp,
|
||||
nonce: vaa.nonce,
|
||||
emitter_chain: vaa.emitter_chain,
|
||||
emitter_address: vaa.emitter_address,
|
||||
sequence: vaa.sequence,
|
||||
consistency_level: vaa.consistency_level,
|
||||
payload: vaa.payload,
|
||||
};
|
||||
let ix = register_chain(
|
||||
program_id,
|
||||
bridge_id,
|
||||
payer,
|
||||
message_key,
|
||||
post_vaa_data,
|
||||
payload,
|
||||
RegisterChainData {},
|
||||
)
|
||||
.unwrap();
|
||||
return JsValue::from_serde(&ix).unwrap();
|
||||
}
|
Loading…
Reference in New Issue