Skip to content

Commit f1a5568

Browse files
committed
solana: add token-router-sdk
1 parent 5a541ed commit f1a5568

File tree

10 files changed

+154
-52
lines changed

10 files changed

+154
-52
lines changed

solana/Cargo.lock

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[package]
2+
name = "token-router-sdk"
3+
edition.workspace = true
4+
version.workspace = true
5+
authors.workspace = true
6+
license.workspace = true
7+
homepage.workspace = true
8+
repository.workspace = true
9+
10+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
11+
12+
[features]
13+
testnet = ["token-router/testnet"]
14+
localnet = ["token-router/localnet"]
15+
16+
[dependencies]
17+
token-router = { workspace = true, features = ["cpi"] }
18+
19+
wormhole-io.workspace = true
20+
anchor-lang.workspace = true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
mod prepared_fill;
2+
pub use prepared_fill::*;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use std::ops::Deref;
2+
3+
use anchor_lang::{prelude::*, Discriminator};
4+
use token_router::state::PreparedFillInfo;
5+
use wormhole_io::{Readable, TypePrefixedPayload};
6+
7+
#[derive(Debug, AnchorSerialize, AnchorDeserialize, Clone)]
8+
pub struct PreparedFill<P: TypePrefixedPayload> {
9+
pub info: PreparedFillInfo,
10+
pub message_size: u32,
11+
pub redeemer_message: P,
12+
}
13+
14+
impl<P: TypePrefixedPayload> Owner for PreparedFill<P> {
15+
fn owner() -> Pubkey {
16+
token_router::ID
17+
}
18+
}
19+
20+
impl<P: TypePrefixedPayload> Discriminator for PreparedFill<P> {
21+
const DISCRIMINATOR: [u8; 8] = token_router::state::PreparedFill::DISCRIMINATOR;
22+
}
23+
24+
impl<P: TypePrefixedPayload> AccountSerialize for PreparedFill<P> {
25+
fn try_serialize<W: std::io::prelude::Write>(&self, writer: &mut W) -> Result<()> {
26+
Self::DISCRIMINATOR.serialize(writer)?;
27+
self.info.serialize(writer)?;
28+
self.message_size.serialize(writer)?;
29+
self.redeemer_message.write(writer)?;
30+
Ok(())
31+
}
32+
}
33+
34+
impl<P: TypePrefixedPayload> AccountDeserialize for PreparedFill<P> {
35+
fn try_deserialize(buf: &mut &[u8]) -> Result<Self> {
36+
let disc_len = Self::DISCRIMINATOR.len();
37+
if buf.len() < disc_len {
38+
return err!(ErrorCode::AccountDidNotDeserialize);
39+
};
40+
if Self::DISCRIMINATOR != buf[..disc_len] {
41+
return err!(ErrorCode::AccountDidNotDeserialize);
42+
}
43+
Self::try_deserialize_unchecked(buf)
44+
}
45+
46+
fn try_deserialize_unchecked(buf: &mut &[u8]) -> Result<Self> {
47+
let mut data = &buf[Self::DISCRIMINATOR.len()..];
48+
Ok(Self {
49+
info: AnchorDeserialize::deserialize(&mut data)?,
50+
message_size: AnchorDeserialize::deserialize(&mut data)?,
51+
redeemer_message: Readable::read(&mut data)?,
52+
})
53+
}
54+
}
55+
56+
impl<P: TypePrefixedPayload> Deref for PreparedFill<P> {
57+
type Target = PreparedFillInfo;
58+
59+
fn deref(&self) -> &Self::Target {
60+
&self.info
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub mod accounts;
2+
3+
pub use token_router::cpi::*;

solana/programs/token-router/src/processor/redeem_fill/cctp.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
error::TokenRouterError,
3-
state::{Custodian, FillType, PreparedFill},
3+
state::{Custodian, FillType, PreparedFill, PreparedFillInfo},
44
};
55
use anchor_lang::{prelude::*, system_program};
66
use anchor_spl::token;
@@ -263,14 +263,16 @@ fn handle_redeem_fill_cctp(ctx: Context<RedeemCctpFill>, args: CctpMessageArgs)
263263

264264
// Set prepared fill data.
265265
ctx.accounts.prepared_fill.set_inner(PreparedFill {
266-
vaa_hash: vaa.digest().0,
267-
bump: ctx.bumps.prepared_fill,
268-
prepared_custody_token_bump: ctx.bumps.prepared_custody_token,
269-
redeemer: Pubkey::from(fill.redeemer()),
270-
prepared_by: ctx.accounts.payer.key(),
271-
fill_type: FillType::WormholeCctpDeposit,
272-
source_chain: fill.source_chain(),
273-
order_sender: fill.order_sender(),
266+
info: PreparedFillInfo {
267+
vaa_hash: vaa.digest().0,
268+
bump: ctx.bumps.prepared_fill,
269+
prepared_custody_token_bump: ctx.bumps.prepared_custody_token,
270+
redeemer: Pubkey::from(fill.redeemer()),
271+
prepared_by: ctx.accounts.payer.key(),
272+
fill_type: FillType::WormholeCctpDeposit,
273+
source_chain: fill.source_chain(),
274+
order_sender: fill.order_sender(),
275+
},
274276
redeemer_message: fill.message_to_vec(),
275277
});
276278

solana/programs/token-router/src/processor/redeem_fill/fast.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
error::TokenRouterError,
3-
state::{Custodian, FillType, PreparedFill},
3+
state::{Custodian, FillType, PreparedFill, PreparedFillInfo},
44
};
55
use anchor_lang::{prelude::*, system_program};
66
use anchor_spl::token;
@@ -150,14 +150,16 @@ fn handle_redeem_fast_fill(ctx: Context<RedeemFastFill>) -> Result<()> {
150150

151151
// Set prepared fill data.
152152
ctx.accounts.prepared_fill.set_inner(PreparedFill {
153-
vaa_hash: vaa.digest().0,
154-
bump: ctx.bumps.prepared_fill,
155-
prepared_custody_token_bump: ctx.bumps.prepared_custody_token,
156-
redeemer: Pubkey::from(fill.redeemer()),
157-
prepared_by: ctx.accounts.payer.key(),
158-
fill_type: FillType::FastFill,
159-
source_chain: fill.source_chain(),
160-
order_sender: fill.order_sender(),
153+
info: PreparedFillInfo {
154+
vaa_hash: vaa.digest().0,
155+
bump: ctx.bumps.prepared_fill,
156+
prepared_custody_token_bump: ctx.bumps.prepared_custody_token,
157+
redeemer: Pubkey::from(fill.redeemer()),
158+
prepared_by: ctx.accounts.payer.key(),
159+
fill_type: FillType::FastFill,
160+
source_chain: fill.source_chain(),
161+
order_sender: fill.order_sender(),
162+
},
161163
redeemer_message: fill.message_to_vec(),
162164
});
163165

solana/programs/token-router/src/state/prepared_fill.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ pub enum FillType {
77
FastFill,
88
}
99

10-
#[account]
11-
#[derive(Debug)]
12-
pub struct PreparedFill {
10+
#[derive(Debug, AnchorSerialize, AnchorDeserialize, Clone, InitSpace)]
11+
pub struct PreparedFillInfo {
1312
pub vaa_hash: [u8; 32],
1413
pub bump: u8,
1514
pub prepared_custody_token_bump: u8,
@@ -21,6 +20,12 @@ pub struct PreparedFill {
2120
pub source_chain: u16,
2221
pub order_sender: [u8; 32],
2322
pub redeemer: Pubkey,
23+
}
24+
25+
#[account]
26+
#[derive(Debug)]
27+
pub struct PreparedFill {
28+
pub info: PreparedFillInfo,
2429
pub redeemer_message: Vec<u8>,
2530
}
2631

@@ -31,3 +36,11 @@ impl PreparedFill {
3136
8 + 32 + 1 + 32 + 32 + FillType::INIT_SPACE + 8 + 2 + 32 + 4 + payload_len
3237
}
3338
}
39+
40+
impl std::ops::Deref for PreparedFill {
41+
type Target = PreparedFillInfo;
42+
43+
fn deref(&self) -> &Self::Target {
44+
&self.info
45+
}
46+
}

solana/ts/src/tokenRouter/state/PreparedFill.ts

+7-21
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export type FillType = {
77
fastFill?: {};
88
};
99

10-
export class PreparedFill {
10+
export type PreparedFillInfo = {
1111
vaaHash: Array<number>;
1212
bump: number;
1313
preparedCustodyTokenBump: number;
@@ -16,28 +16,14 @@ export class PreparedFill {
1616
sourceChain: number;
1717
orderSender: Array<number>;
1818
redeemer: PublicKey;
19+
};
20+
21+
export class PreparedFill {
22+
info: PreparedFillInfo;
1923
redeemerMessage: Buffer;
2024

21-
constructor(
22-
vaaHash: Array<number>,
23-
bump: number,
24-
preparedCustodyTokenBump: number,
25-
redeemer: PublicKey,
26-
preparedBy: PublicKey,
27-
fillType: FillType,
28-
amount: BN,
29-
sourceChain: number,
30-
orderSender: Array<number>,
31-
redeemerMessage: Buffer,
32-
) {
33-
this.vaaHash = vaaHash;
34-
this.bump = bump;
35-
this.preparedCustodyTokenBump = preparedCustodyTokenBump;
36-
this.preparedBy = preparedBy;
37-
this.fillType = fillType;
38-
this.sourceChain = sourceChain;
39-
this.orderSender = orderSender;
40-
this.redeemer = redeemer;
25+
constructor(info: PreparedFillInfo, redeemerMessage: Buffer) {
26+
this.info = info;
4127
this.redeemerMessage = redeemerMessage;
4228
}
4329

solana/ts/tests/04__interaction.ts

+13-10
Original file line numberDiff line numberDiff line change
@@ -364,18 +364,21 @@ describe("Matching Engine <> Token Router", function () {
364364

365365
{
366366
const preparedFillData = await tokenRouter.fetchPreparedFill(preparedFill);
367-
const { bump, preparedCustodyTokenBump } = preparedFillData;
367+
const {
368+
info: { bump, preparedCustodyTokenBump },
369+
} = preparedFillData;
368370
expect(preparedFillData).to.eql(
369371
new tokenRouterSdk.PreparedFill(
370-
Array.from(vaaHash),
371-
bump,
372-
preparedCustodyTokenBump,
373-
redeemer.publicKey,
374-
payer.publicKey,
375-
{ fastFill: {} },
376-
bigintToU64BN(amount),
377-
foreignChain,
378-
orderSender,
372+
{
373+
vaaHash: Array.from(vaaHash),
374+
bump,
375+
preparedCustodyTokenBump,
376+
redeemer: redeemer.publicKey,
377+
preparedBy: payer.publicKey,
378+
fillType: { fastFill: {} },
379+
sourceChain: foreignChain,
380+
orderSender,
381+
},
379382
redeemerMessage,
380383
),
381384
);

0 commit comments

Comments
 (0)