-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* StagedTXInstruction -> TXInstructionBuffer * Scaffold instruction handlers * Implement InitIxBuffer handler * Implement writeTx * Implement execut_ix * Fixup * Fixes * Test write then execute * Test write and execute multiple instructions * close_ix_buffer * Test close buffer * Account validations * clippy * Update docs * Add events * Fix doc
- Loading branch information
1 parent
fc4594c
commit ec0cc48
Showing
13 changed files
with
438 additions
and
22 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
//! Init or close an [InstructionBuffer]. | ||
|
||
use crate::*; | ||
|
||
#[derive(Accounts)] | ||
pub struct InitIxBuffer<'info> { | ||
#[account(zero)] | ||
pub buffer: Account<'info, InstructionBuffer>, | ||
/// CHECK: Writer account that can write to the buffer. | ||
pub writer: UncheckedAccount<'info>, | ||
} | ||
|
||
/// Emitted when a [InstructionBuffer] is initialized. | ||
#[event] | ||
pub struct InitBufferEvent { | ||
/// The [InstructionBuffer::writer]. | ||
#[index] | ||
pub writer: Pubkey, | ||
/// The buffer. | ||
pub buffer: Pubkey, | ||
} | ||
|
||
pub fn handle_init(ctx: Context<InitIxBuffer>) -> Result<()> { | ||
let buffer = &mut ctx.accounts.buffer; | ||
buffer.writer = ctx.accounts.writer.key(); | ||
|
||
emit!(InitBufferEvent { | ||
writer: buffer.writer, | ||
buffer: buffer.key() | ||
}); | ||
|
||
Ok(()) | ||
} | ||
|
||
impl<'info> Validate<'info> for InitIxBuffer<'info> { | ||
fn validate(&self) -> Result<()> { | ||
Ok(()) | ||
} | ||
} | ||
|
||
#[derive(Accounts)] | ||
pub struct CloseIxBuffer<'info> { | ||
#[account(mut, close = writer)] | ||
pub buffer: Account<'info, InstructionBuffer>, | ||
pub writer: Signer<'info>, | ||
} | ||
|
||
/// Emitted when an [InstructionBuffer] is closed. | ||
#[event] | ||
pub struct CloseBufferEvent { | ||
/// The [InstructionBuffer::writer]. | ||
#[index] | ||
pub writer: Pubkey, | ||
/// The buffer. | ||
pub buffer: Pubkey, | ||
} | ||
|
||
pub fn handle_close(ctx: Context<CloseIxBuffer>) -> Result<()> { | ||
emit!(CloseBufferEvent { | ||
writer: ctx.accounts.writer.key(), | ||
buffer: ctx.accounts.buffer.key(), | ||
}); | ||
Ok(()) | ||
} | ||
|
||
impl<'info> Validate<'info> for CloseIxBuffer<'info> { | ||
fn validate(&self) -> Result<()> { | ||
assert_keys_eq!(self.writer.key(), self.buffer.writer); | ||
|
||
Ok(()) | ||
} | ||
} |
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 @@ | ||
//! Executes an instruction off of the [InstructionBuffer]. | ||
|
||
use anchor_lang::solana_program::program::invoke; | ||
|
||
use crate::*; | ||
|
||
#[derive(Accounts)] | ||
pub struct ExecuteIx<'info> { | ||
#[account(mut)] | ||
pub buffer: Box<Account<'info, InstructionBuffer>>, | ||
} | ||
|
||
pub fn handler<'info>(ctx: Context<'_, '_, '_, 'info, ExecuteIx<'info>>) -> Result<()> { | ||
let buffer = &mut ctx.accounts.buffer; | ||
let ix = &buffer.staged_tx_instructions[buffer.exec_count as usize]; | ||
invoke(&ix.into(), ctx.remaining_accounts)?; | ||
buffer.exec_count += 1; | ||
|
||
Ok(()) | ||
} | ||
|
||
impl<'info> Validate<'info> for ExecuteIx<'info> { | ||
fn validate(&self) -> Result<()> { | ||
invariant!(self.buffer.exec_count < self.buffer.staged_tx_instructions.len() as u8); | ||
|
||
Ok(()) | ||
} | ||
} |
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,7 @@ | ||
pub mod buffer; | ||
pub mod execute_ix; | ||
pub mod write_ix; | ||
|
||
pub use buffer::*; | ||
pub use execute_ix::*; | ||
pub use write_ix::*; |
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,43 @@ | ||
//! Writes an instruction to the [InstructionBuffer]. | ||
|
||
use crate::*; | ||
|
||
#[derive(Accounts)] | ||
pub struct WriteIx<'info> { | ||
#[account(mut)] | ||
pub buffer: Box<Account<'info, InstructionBuffer>>, | ||
pub writer: Signer<'info>, | ||
} | ||
|
||
/// Emitted when an instruction is written to the [InstructionBuffer]. | ||
#[event] | ||
pub struct WriteIxEvent { | ||
/// The [InstructionBuffer]. | ||
pub buffer: Pubkey, | ||
/// The [InstructionBuffer::writer]. | ||
pub writer: Pubkey, | ||
/// The program id of the instruction written. | ||
pub program_id: Pubkey, | ||
} | ||
|
||
pub fn handler(ctx: Context<WriteIx>, ix: TXInstruction) -> Result<()> { | ||
let buffer = &mut ctx.accounts.buffer; | ||
|
||
emit!(WriteIxEvent { | ||
buffer: buffer.key(), | ||
writer: buffer.writer, | ||
program_id: ix.program_id | ||
}); | ||
|
||
buffer.staged_tx_instructions.push(ix); | ||
|
||
Ok(()) | ||
} | ||
|
||
impl<'info> Validate<'info> for WriteIx<'info> { | ||
fn validate(&self) -> Result<()> { | ||
assert_keys_eq!(self.writer.key(), self.buffer.writer); | ||
|
||
Ok(()) | ||
} | ||
} |
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
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,110 @@ | ||
import { TransactionEnvelope } from "@saberhq/solana-contrib"; | ||
import type { | ||
AccountMeta, | ||
PublicKey, | ||
TransactionInstruction, | ||
} from "@solana/web3.js"; | ||
import { Keypair } from "@solana/web3.js"; | ||
|
||
import type { SmartWalletProgram } from "../../programs"; | ||
import type { InstructionBufferData } from "../../programs/smartWallet"; | ||
import type { GokiSDK } from "../../sdk"; | ||
import type { PendingBuffer } from "./types"; | ||
|
||
export class InstructionLoaderWrapper { | ||
readonly program: SmartWalletProgram; | ||
|
||
constructor(readonly sdk: GokiSDK) { | ||
this.program = sdk.programs.SmartWallet; | ||
} | ||
|
||
/** | ||
* loadBufferData | ||
* @returns | ||
*/ | ||
async loadBufferData( | ||
bufferAccount: PublicKey | ||
): Promise<InstructionBufferData> { | ||
return await this.program.account.instructionBuffer.fetch(bufferAccount); | ||
} | ||
|
||
/** | ||
* Initialize a loader buffer. | ||
*/ | ||
async initBuffer( | ||
bufferSize: number, | ||
writer: PublicKey = this.sdk.provider.wallet.publicKey, | ||
bufferAccount: Keypair = Keypair.generate() | ||
): Promise<PendingBuffer> { | ||
const tx = new TransactionEnvelope( | ||
this.sdk.provider, | ||
[ | ||
await this.program.account.instructionBuffer.createInstruction( | ||
bufferAccount, | ||
this.program.account.instructionBuffer.size + bufferSize | ||
), | ||
this.program.instruction.initIxBuffer({ | ||
accounts: { | ||
buffer: bufferAccount.publicKey, | ||
writer, | ||
}, | ||
}), | ||
], | ||
[bufferAccount] | ||
); | ||
|
||
return { | ||
tx, | ||
bufferAccount: bufferAccount.publicKey, | ||
}; | ||
} | ||
|
||
closeBuffer( | ||
bufferAccount: PublicKey, | ||
writer: PublicKey = this.sdk.provider.wallet.publicKey | ||
): TransactionEnvelope { | ||
return new TransactionEnvelope(this.sdk.provider, [ | ||
this.program.instruction.closeIxBuffer({ | ||
accounts: { | ||
buffer: bufferAccount, | ||
writer, | ||
}, | ||
}), | ||
]); | ||
} | ||
|
||
/** | ||
* Executes an instruction from the buffer. | ||
*/ | ||
executeInstruction( | ||
bufferAccount: PublicKey, | ||
accountMetas: AccountMeta[] | ||
): TransactionEnvelope { | ||
return new TransactionEnvelope(this.sdk.provider, [ | ||
this.program.instruction.executeIx({ | ||
accounts: { | ||
buffer: bufferAccount, | ||
}, | ||
remainingAccounts: accountMetas, | ||
}), | ||
]); | ||
} | ||
|
||
/** | ||
* Write an instruction to the buffer. | ||
*/ | ||
writeInstruction( | ||
ix: TransactionInstruction, | ||
bufferAccount: PublicKey, | ||
writer: PublicKey = this.sdk.provider.wallet.publicKey | ||
): TransactionEnvelope { | ||
return new TransactionEnvelope(this.sdk.provider, [ | ||
this.program.instruction.writeIx(ix, { | ||
accounts: { | ||
buffer: bufferAccount, | ||
writer, | ||
}, | ||
}), | ||
]); | ||
} | ||
} |
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,6 @@ | ||
import type { PublicKey, TransactionEnvelope } from "@saberhq/solana-contrib"; | ||
|
||
export type PendingBuffer = { | ||
tx: TransactionEnvelope; | ||
bufferAccount: PublicKey; | ||
}; |
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
Oops, something went wrong.