added solana readmd

This commit is contained in:
ceun 2022-05-20 15:45:06 +00:00
parent 57704ed023
commit 2df20cceaf
3 changed files with 88 additions and 8 deletions

45
solana/README.md Normal file
View File

@ -0,0 +1,45 @@
Scenario: User from Chain A wants to swap Token A for Token B on Chain B.
Step 1: User transfers Token A to Native Swap through the token bridge
Step 2: Native Swap redeems the transfer from the token bridge and takes custody of the wrapped-Token A
Step 3a: for "NoSwap", Native Swap sends wrapped-Token A to recipient wallet on Chain B.
Step 3b: for "WithSwap", Native Swap swaps wrapped-Token A for Token B and sends Token B to recipient wallet on Chain B
Instruction::CompleteTransfer
Description: redeems wrapped tokens from the token bridge ATA, transfers them to the NativeSwap ATA.
Extremely similar to CompleteWrappedWithPayload struct in the token bridge sdk except, instead of the user redeeming the transfer, NativeSwap redeems it.
Instruction::CompleteNoSwap
Description: transfers wrapped tokens from NativeSwap ATA to user's ATA
### Running
Set you id.json to your private key
```
~/.config/solana/id.json
```
Build the cargo
```
EMITTER_ADDRESS=EMITTER_ADDRESS BRIDGE_ADDRESS=BRIDGE_ADDRESS TOKEN_BRIDGE_ADDRESS=TOKEN_BRIDGE_ADDRESS cargo build-bpf
```
Write the program byte code into a buffer address
```
solana program write-buffer target/deploy/wormhole_nativeswap.so -u d
```
Take the buffer address & Deploy the contract
```
solana program deploy --program-id PROGRAM_ID --buffer BUFFER -u d
>in testnet (solana devnet), PROGRAM_ID=92XVWWdN47dL38HLZ277rdRJh7RUG2ikmiBRoUGrKXif
```
Compile the wasm bindings
```
EMITTER_ADDRESS="11111111111111111111111111111115" BRIDGE_ADDRESS="3u8hJUVTA4jH1wYAyUur7FFZVQ8H635K3tSHHF4ssjQ5" TOKEN_BRIDGE_ADDRESS="DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe" wasm-pack build --target nodejs -d nodejs -- --features wasm
```
Now the wasm node package is ready to use.
```
cd test
MNEMONIC=PRIVATE_KEY node index.js
```
transfer_ix: the transfer instruction to redeem the tokens from the token bridge and transfer them to NativeSwap. you have to submit a tokenTransfer VAA where the recipient is the custody address
no_swap_ix: the transfer instruction to move the tokens from NativeSwap to the recipients wallet.

View File

@ -32,6 +32,9 @@ use solitaire::{
*,
};
// have to create custom config account for the token bridge b/c the default ConfigAccount in solana/modules/token_bridge/program/src/accounts.rs
// is a derived account and assumes the program id is the ExecutionContext,
// which is normally the token bridge... but in this case would be NativeSwap.
pub type TokenBridgeConfigAccount<'b, const STATE: AccountState> = Data<'b, Config, { STATE }>;
pub struct TokenBridgeConfigAccountDerivationData {
@ -49,7 +52,8 @@ impl<'b, const STATE: AccountState> Seeded<&TokenBridgeConfigAccountDerivationDa
}
}
pub type TokenBridgeMintSigner<'b> = Info<'b>;
//Info is short alias for AccountInfo from solana programs
pub type TokenBridgeMintSigner<'b> = Info<'b>;
pub struct TokenBridgeMintSignerDerivationData {
pub token_bridge: Pubkey,
@ -66,6 +70,27 @@ impl<'b> Seeded<&TokenBridgeMintSignerDerivationData>
}
}
/*
#[derive(FromAccounts)]
pub struct CompleteWrappedWithPayload<'b> {
pub payer: Mut<Signer<AccountInfo<'b>>>,
pub config: ConfigAccount<'b, { AccountState::Initialized }>,
// Signed message for the transfer
pub vaa: ClaimableVAA<'b, PayloadTransferWithPayload>,
pub chain_registration: Endpoint<'b, { AccountState::Initialized }>,
pub to: Mut<Data<'b, SplAccount, { AccountState::Initialized }>>,
pub to_owner: MaybeMut<Signer<Info<'b>>>,
pub to_fees: Mut<Data<'b, SplAccount, { AccountState::Initialized }>>,
pub mint: Mut<WrappedMint<'b, { AccountState::Initialized }>>,
pub wrapped_meta: WrappedTokenMeta<'b, { AccountState::Initialized }>,
pub mint_authority: MintSigner<'b>,
}
*/
#[derive(FromAccounts)]
pub struct CompleteTransfer<'b> {
pub payer: Mut<Signer<AccountInfo<'b>>>,
@ -76,15 +101,16 @@ pub struct CompleteTransfer<'b> {
// Above includes claim account
pub chain_registration: Endpoint<'b, { AccountState::Initialized }>,
// custody == Native Swap ATA
pub custody: Mut<CustodyAccount<'b, { AccountState::MaybeInitialized }>>,
// custody signer == PDA of Native Swap Program ID
pub custody_signer: CustodySigner<'b>,
pub to_fees: Mut<Data<'b, SplAccount, { AccountState::MaybeInitialized }>>,
pub mint: Mut<WrappedMint<'b, { AccountState::Initialized }>>,
pub wrapped_meta: WrappedTokenMeta<'b, { AccountState::Initialized }>,
pub mint_authority: TokenBridgeMintSigner<'b>,
pub token_bridge: Info<'b>,
pub token_bridge: Info<'b>, //<-- added for derived config, endpoint, & wrapped metadata
}
impl<'a> From<&CompleteTransfer<'a>> for EndpointDerivationData {
@ -105,6 +131,8 @@ impl<'a> From<&CompleteTransfer<'a>> for WrappedDerivationData {
}
}
// have to define implementations for the derived data similar to CompleteWrappedWithPayload
impl<'a> From<&CompleteTransfer<'a>> for CustodyAccountDerivationData {
fn from(accs: &CompleteTransfer<'a>) -> Self {
CustodyAccountDerivationData {
@ -125,15 +153,19 @@ pub fn complete_transfer(
_data: CompleteTransferData,
) -> Result<()> {
msg!("program id: {:?}", ctx.program_id);
msg!("accounts: {:?}", ctx.accounts);
// core bridge
let bridge_id = ctx.accounts[14].info().key;
//where the payload/postedVaa is being stored
let message_key = ctx.accounts[2].info().key;
msg!("bridge_id: {:?}", bridge_id);
msg!("message_key: {:?}", message_key);
// Verify that the custody account is derived correctly
// Verify that the custody account is a ATA of custody owner aka native swap
let derivation_data: CustodyAccountDerivationData = (&*accs).into();
accs.custody
.verify_derivation(ctx.program_id, &derivation_data)?;
// if the ATA of the wrapped token belonging to NativeSwap is not created, create it
if !accs.custody.is_initialized() {
accs.custody
.create(&(&*accs).into(), ctx, accs.payer.key, Exempt)?;
@ -149,7 +181,8 @@ pub fn complete_transfer(
// see https://github.com/certusone/wormhole/blob/2e24f11fa045ac8460347d9796a4ecdb7931a154/solana/modules/token_bridge/program/src/instructions.rs#L312-L338
// TODO: maybe there's a better way to rebuild this off our list of accounts which should be nearly compatible
// transfer the wrapped token from the token bridge ATA to the NativeSwap ATA
let transfer_ix = Instruction {
program_id: *accs.token_bridge.info().key,
accounts: vec![

View File

@ -1,3 +1,5 @@
const { uint8ArrayToNative } = require("@certusone/wormhole-sdk");
(async () => {
const PAYLOAD_1_VAA =
"01000000000100339c0d030b927eda9cb7ee53d266cbdc6d8f2a70a2a8031952a3a19ee3963d77030dfa8d70c134ef577f9db119cd606bf82ad593f6bb5addfc57f33e741e7e6201624b367c636d0000000b000000000000000000000000d11de1f930ea1f7dd0290fe3a2e35b9c91aefb37000000000000000c010100000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000337610d27c682e347c9cd60bd4b3b107c9d34ddd000400000000000000000000000012345756e90eba0c357d6ea5d537a179f9d6d0b000040000000000000000000000000000000000000000000000000000000000000000";
@ -53,6 +55,7 @@
sdk.hexToUint8Array(PAYLOAD_3_VAA_TO_SOLANA_WITH_CUSTODY_SIGNER2)
);
console.log(transfer_ix_json);
console.log("Program Id:", sdk.uint8ArrayToNative(transfer_ix_json.program_id, 1))
console.log(
transfer_ix_json.accounts.map(({ pubkey, is_signer, is_writable }) => [
sdk.hexToNativeString(
@ -84,7 +87,6 @@
])
);
const transfer_ix = sdk.ixFromRust(transfer_ix_json);
const no_swap_ix = sdk.ixFromRust(no_swap_ix_json);