lang, spl: Program and Signer types (#705)
This commit is contained in:
parent
e2bd41b967
commit
b1ef7431ec
|
@ -11,6 +11,11 @@ incremented for features.
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Features
|
||||
|
||||
* lang: `Program` type introduced for executable accounts ([#705](https://github.com/project-serum/anchor/pull/705)).
|
||||
* lang: `Signer` type introduced for signing accounts where data is not used ([#705](https://github.com/project-serum/anchor/pull/705)).
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* lang: `#[account(owner = <pubkey>)]` now requires a `Pubkey` instead of an account ([#691](https://github.com/project-serum/anchor/pull/691)).
|
||||
|
|
|
@ -2,5 +2,8 @@
|
|||
cluster = "localnet"
|
||||
wallet = "~/.config/solana/id.json"
|
||||
|
||||
[programs.localnet]
|
||||
basic_0 = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
|
||||
|
||||
[scripts]
|
||||
test = "mocha -t 1000000 tests/"
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
||||
|
||||
#[program]
|
||||
mod basic_0 {
|
||||
use super::*;
|
||||
|
|
|
@ -23,8 +23,9 @@ mod basic_1 {
|
|||
pub struct Initialize<'info> {
|
||||
#[account(init, payer = user, space = 8 + 8)]
|
||||
pub my_account: Account<'info, MyAccount>,
|
||||
pub user: AccountInfo<'info>,
|
||||
pub system_program: AccountInfo<'info>,
|
||||
#[account(mut)]
|
||||
pub user: Signer<'info>,
|
||||
pub system_program: Program<'info, System>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use anchor_lang::solana_program::system_program;
|
||||
|
||||
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
||||
|
||||
|
@ -25,18 +24,16 @@ mod basic_2 {
|
|||
pub struct Create<'info> {
|
||||
#[account(init, payer = user, space = 8 + 40)]
|
||||
pub counter: Account<'info, Counter>,
|
||||
#[account(signer)]
|
||||
pub user: AccountInfo<'info>,
|
||||
#[account(address = system_program::ID)]
|
||||
pub system_program: AccountInfo<'info>,
|
||||
#[account(mut)]
|
||||
pub user: Signer<'info>,
|
||||
pub system_program: Program<'info, System>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct Increment<'info> {
|
||||
#[account(mut, has_one = authority)]
|
||||
pub counter: Account<'info, Counter>,
|
||||
#[account(signer)]
|
||||
pub authority: AccountInfo<'info>,
|
||||
pub authority: Signer<'info>,
|
||||
}
|
||||
|
||||
#[account]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// #region core
|
||||
use anchor_lang::prelude::*;
|
||||
use puppet::{self, Puppet, SetData};
|
||||
use puppet::program::Puppet;
|
||||
use puppet::{self, Data, SetData};
|
||||
|
||||
declare_id!("HmbTLCmaGvZhKnn1Zfa1JVnp7vkMV4DYVxPLWBVoN65L");
|
||||
|
||||
|
@ -8,7 +9,7 @@ declare_id!("HmbTLCmaGvZhKnn1Zfa1JVnp7vkMV4DYVxPLWBVoN65L");
|
|||
mod puppet_master {
|
||||
use super::*;
|
||||
pub fn pull_strings(ctx: Context<PullStrings>, data: u64) -> ProgramResult {
|
||||
let cpi_program = ctx.accounts.puppet_program.clone();
|
||||
let cpi_program = ctx.accounts.puppet_program.to_account_info();
|
||||
let cpi_accounts = SetData {
|
||||
puppet: ctx.accounts.puppet.clone(),
|
||||
};
|
||||
|
@ -20,8 +21,7 @@ mod puppet_master {
|
|||
#[derive(Accounts)]
|
||||
pub struct PullStrings<'info> {
|
||||
#[account(mut)]
|
||||
pub puppet: Account<'info, Puppet>,
|
||||
#[account(address = puppet::ID)]
|
||||
pub puppet_program: AccountInfo<'info>,
|
||||
pub puppet: Account<'info, Data>,
|
||||
pub puppet_program: Program<'info, Puppet>,
|
||||
}
|
||||
// #endregion core
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use anchor_lang::solana_program::system_program;
|
||||
|
||||
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
||||
|
||||
#[program]
|
||||
pub mod puppet {
|
||||
use super::*;
|
||||
pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {
|
||||
pub fn initialize(_ctx: Context<Initialize>) -> ProgramResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -20,20 +19,19 @@ pub mod puppet {
|
|||
#[derive(Accounts)]
|
||||
pub struct Initialize<'info> {
|
||||
#[account(init, payer = user, space = 8 + 8)]
|
||||
pub puppet: Account<'info, Puppet>,
|
||||
#[account(signer)]
|
||||
pub user: AccountInfo<'info>,
|
||||
#[account(address = system_program::ID)]
|
||||
pub system_program: AccountInfo<'info>,
|
||||
pub puppet: Account<'info, Data>,
|
||||
#[account(mut)]
|
||||
pub user: Signer<'info>,
|
||||
pub system_program: Program<'info, System>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct SetData<'info> {
|
||||
#[account(mut)]
|
||||
pub puppet: Account<'info, Puppet>,
|
||||
pub puppet: Account<'info, Data>,
|
||||
}
|
||||
|
||||
#[account]
|
||||
pub struct Puppet {
|
||||
pub struct Data {
|
||||
pub data: u64,
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ describe("basic-3", () => {
|
|||
});
|
||||
|
||||
// Check the state updated.
|
||||
puppetAccount = await puppet.account.puppet.fetch(newPuppetAccount.publicKey);
|
||||
puppetAccount = await puppet.account.data.fetch(newPuppetAccount.publicKey);
|
||||
assert.ok(puppetAccount.data.eq(new anchor.BN(111)));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -33,8 +33,7 @@ pub mod basic_4 {
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct Auth<'info> {
|
||||
#[account(signer)]
|
||||
authority: AccountInfo<'info>,
|
||||
authority: Signer<'info>,
|
||||
}
|
||||
// #endregion code
|
||||
|
||||
|
|
|
@ -66,6 +66,12 @@ pub enum ErrorCode {
|
|||
AccountNotMutable,
|
||||
#[msg("The given account is not owned by the executing program")]
|
||||
AccountNotProgramOwned,
|
||||
#[msg("Program ID was not as expected")]
|
||||
InvalidProgramId,
|
||||
#[msg("Program account is not executable")]
|
||||
InvalidProgramExecutable,
|
||||
#[msg("The given account did not sign")]
|
||||
AccountNotSigner,
|
||||
|
||||
// State.
|
||||
#[msg("The given state account does not have the correct address")]
|
||||
|
|
|
@ -44,8 +44,11 @@ mod error;
|
|||
#[doc(hidden)]
|
||||
pub mod idl;
|
||||
mod loader;
|
||||
mod program;
|
||||
mod program_account;
|
||||
mod signer;
|
||||
pub mod state;
|
||||
mod system_program;
|
||||
mod sysvar;
|
||||
mod vec;
|
||||
|
||||
|
@ -61,12 +64,15 @@ pub use crate::cpi_account::CpiAccount;
|
|||
#[allow(deprecated)]
|
||||
pub use crate::cpi_state::CpiState;
|
||||
pub use crate::loader::Loader;
|
||||
pub use crate::program::Program;
|
||||
#[doc(hidden)]
|
||||
#[allow(deprecated)]
|
||||
pub use crate::program_account::ProgramAccount;
|
||||
pub use crate::signer::Signer;
|
||||
#[doc(hidden)]
|
||||
#[allow(deprecated)]
|
||||
pub use crate::state::ProgramState;
|
||||
pub use crate::system_program::System;
|
||||
pub use crate::sysvar::Sysvar;
|
||||
pub use anchor_attribute_access_control::access_control;
|
||||
pub use anchor_attribute_account::{account, declare_id, zero_copy};
|
||||
|
@ -217,6 +223,11 @@ pub trait Owner {
|
|||
fn owner() -> Pubkey;
|
||||
}
|
||||
|
||||
/// Defines the id of a program.
|
||||
pub trait Id {
|
||||
fn id() -> Pubkey;
|
||||
}
|
||||
|
||||
/// Defines the Pubkey of an account.
|
||||
pub trait Key {
|
||||
fn key(&self) -> Pubkey;
|
||||
|
@ -234,8 +245,8 @@ pub mod prelude {
|
|||
pub use super::{
|
||||
access_control, account, declare_id, emit, error, event, interface, program, require,
|
||||
state, zero_copy, Account, AccountDeserialize, AccountSerialize, Accounts, AccountsExit,
|
||||
AnchorDeserialize, AnchorSerialize, Context, CpiContext, Key, Loader, Owner,
|
||||
ProgramAccount, Sysvar, ToAccountInfo, ToAccountInfos, ToAccountMetas,
|
||||
AnchorDeserialize, AnchorSerialize, Context, CpiContext, Key, Loader, Owner, Program,
|
||||
ProgramAccount, Signer, System, Sysvar, ToAccountInfo, ToAccountInfos, ToAccountMetas,
|
||||
};
|
||||
|
||||
#[allow(deprecated)]
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
use crate::error::ErrorCode;
|
||||
use crate::*;
|
||||
use solana_program::account_info::AccountInfo;
|
||||
use solana_program::instruction::AccountMeta;
|
||||
use solana_program::program_error::ProgramError;
|
||||
use solana_program::pubkey::Pubkey;
|
||||
use std::ops::Deref;
|
||||
|
||||
/// Account container that checks ownership on deserialization.
|
||||
#[derive(Clone)]
|
||||
pub struct Program<'info, T: Id + AccountDeserialize + Clone> {
|
||||
account: T,
|
||||
info: AccountInfo<'info>,
|
||||
}
|
||||
|
||||
impl<'a, T: Id + AccountDeserialize + Clone> Program<'a, T> {
|
||||
fn new(info: AccountInfo<'a>, account: T) -> Program<'a, T> {
|
||||
Self { info, account }
|
||||
}
|
||||
|
||||
/// Deserializes the given `info` into a `Program`.
|
||||
#[inline(never)]
|
||||
pub fn try_from(info: &AccountInfo<'a>) -> Result<Program<'a, T>, ProgramError> {
|
||||
if info.key != &T::id() {
|
||||
return Err(ErrorCode::InvalidProgramId.into());
|
||||
}
|
||||
if !info.executable {
|
||||
return Err(ErrorCode::InvalidProgramExecutable.into());
|
||||
}
|
||||
// Programs have no data so use an empty slice.
|
||||
let mut empty = &[][..];
|
||||
Ok(Program::new(info.clone(), T::try_deserialize(&mut empty)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info, T: Id + Clone> Accounts<'info> for Program<'info, T>
|
||||
where
|
||||
T: Id + AccountDeserialize,
|
||||
{
|
||||
#[inline(never)]
|
||||
fn try_accounts(
|
||||
_program_id: &Pubkey,
|
||||
accounts: &mut &[AccountInfo<'info>],
|
||||
_ix_data: &[u8],
|
||||
) -> Result<Self, ProgramError> {
|
||||
if accounts.is_empty() {
|
||||
return Err(ErrorCode::AccountNotEnoughKeys.into());
|
||||
}
|
||||
let account = &accounts[0];
|
||||
*accounts = &accounts[1..];
|
||||
Program::try_from(account)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info, T: Id + AccountDeserialize + Clone> ToAccountMetas for Program<'info, T> {
|
||||
fn to_account_metas(&self, is_signer: Option<bool>) -> Vec<AccountMeta> {
|
||||
let is_signer = is_signer.unwrap_or(self.info.is_signer);
|
||||
let meta = match self.info.is_writable {
|
||||
false => AccountMeta::new_readonly(*self.info.key, is_signer),
|
||||
true => AccountMeta::new(*self.info.key, is_signer),
|
||||
};
|
||||
vec![meta]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info, T: Id + AccountDeserialize + Clone> ToAccountInfos<'info> for Program<'info, T> {
|
||||
fn to_account_infos(&self) -> Vec<AccountInfo<'info>> {
|
||||
vec![self.info.clone()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info, T: Id + AccountDeserialize + Clone> ToAccountInfo<'info> for Program<'info, T> {
|
||||
fn to_account_info(&self) -> AccountInfo<'info> {
|
||||
self.info.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info, T: Id + AccountDeserialize + Clone> AsRef<AccountInfo<'info>> for Program<'info, T> {
|
||||
fn as_ref(&self) -> &AccountInfo<'info> {
|
||||
&self.info
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info, T: Id + AccountDeserialize + Clone> Deref for Program<'info, T> {
|
||||
type Target = AccountInfo<'info>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.info
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info, T: AccountDeserialize + Id + Clone> AccountsExit<'info> for Program<'info, T> {
|
||||
fn exit(&self, _program_id: &Pubkey) -> ProgramResult {
|
||||
// No-op.
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
use crate::error::ErrorCode;
|
||||
use crate::*;
|
||||
use solana_program::account_info::AccountInfo;
|
||||
use solana_program::entrypoint::ProgramResult;
|
||||
use solana_program::instruction::AccountMeta;
|
||||
use solana_program::program_error::ProgramError;
|
||||
use solana_program::pubkey::Pubkey;
|
||||
use std::ops::Deref;
|
||||
|
||||
/// Type validating that the account signed the transaction. No other ownership
|
||||
/// or type checks are done. If this is used, one should not try to access the
|
||||
/// underlying account data.
|
||||
#[derive(Clone)]
|
||||
pub struct Signer<'info> {
|
||||
info: AccountInfo<'info>,
|
||||
}
|
||||
|
||||
impl<'info> Signer<'info> {
|
||||
fn new(info: AccountInfo<'info>) -> Signer<'info> {
|
||||
Self { info }
|
||||
}
|
||||
|
||||
/// Deserializes the given `info` into a `Signer`.
|
||||
#[inline(never)]
|
||||
pub fn try_from(info: &AccountInfo<'info>) -> Result<Signer<'info>, ProgramError> {
|
||||
if !info.is_signer {
|
||||
return Err(ErrorCode::AccountNotSigner.into());
|
||||
}
|
||||
Ok(Signer::new(info.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info> Accounts<'info> for Signer<'info> {
|
||||
#[inline(never)]
|
||||
fn try_accounts(
|
||||
_program_id: &Pubkey,
|
||||
accounts: &mut &[AccountInfo<'info>],
|
||||
_ix_data: &[u8],
|
||||
) -> Result<Self, ProgramError> {
|
||||
if accounts.is_empty() {
|
||||
return Err(ErrorCode::AccountNotEnoughKeys.into());
|
||||
}
|
||||
let account = &accounts[0];
|
||||
*accounts = &accounts[1..];
|
||||
Signer::try_from(account)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info> AccountsExit<'info> for Signer<'info> {
|
||||
fn exit(&self, _program_id: &Pubkey) -> ProgramResult {
|
||||
// No-op.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info> ToAccountMetas for Signer<'info> {
|
||||
fn to_account_metas(&self, is_signer: Option<bool>) -> Vec<AccountMeta> {
|
||||
let is_signer = is_signer.unwrap_or(self.info.is_signer);
|
||||
let meta = match self.info.is_writable {
|
||||
false => AccountMeta::new_readonly(*self.info.key, is_signer),
|
||||
true => AccountMeta::new(*self.info.key, is_signer),
|
||||
};
|
||||
vec![meta]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info> ToAccountInfos<'info> for Signer<'info> {
|
||||
fn to_account_infos(&self) -> Vec<AccountInfo<'info>> {
|
||||
vec![self.info.clone()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info> ToAccountInfo<'info> for Signer<'info> {
|
||||
fn to_account_info(&self) -> AccountInfo<'info> {
|
||||
self.info.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info> AsRef<AccountInfo<'info>> for Signer<'info> {
|
||||
fn as_ref(&self) -> &AccountInfo<'info> {
|
||||
&self.info
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info> Deref for Signer<'info> {
|
||||
type Target = AccountInfo<'info>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.info
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info> Key for Signer<'info> {
|
||||
fn key(&self) -> Pubkey {
|
||||
*self.info.key
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
use crate::*;
|
||||
use solana_program::program_error::ProgramError;
|
||||
use solana_program::pubkey::Pubkey;
|
||||
|
||||
pub use solana_program::system_program::ID;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct System;
|
||||
|
||||
impl anchor_lang::AccountDeserialize for System {
|
||||
fn try_deserialize(buf: &mut &[u8]) -> Result<Self, ProgramError> {
|
||||
System::try_deserialize_unchecked(buf)
|
||||
}
|
||||
|
||||
fn try_deserialize_unchecked(_buf: &mut &[u8]) -> Result<Self, ProgramError> {
|
||||
Ok(System)
|
||||
}
|
||||
}
|
||||
|
||||
impl anchor_lang::Id for System {
|
||||
fn id() -> Pubkey {
|
||||
ID
|
||||
}
|
||||
}
|
|
@ -515,7 +515,7 @@ pub fn generate_create_account(
|
|||
&[
|
||||
payer.to_account_info(),
|
||||
#field.to_account_info(),
|
||||
system_program.to_account_info().clone(),
|
||||
system_program.to_account_info(),
|
||||
],
|
||||
&[#seeds_with_nonce],
|
||||
)?;
|
||||
|
@ -535,7 +535,7 @@ pub fn generate_create_account(
|
|||
&[
|
||||
payer.to_account_info(),
|
||||
#field.to_account_info(),
|
||||
system_program.to_account_info().clone(),
|
||||
system_program.to_account_info(),
|
||||
],
|
||||
)?;
|
||||
}
|
||||
|
@ -547,7 +547,7 @@ pub fn generate_create_account(
|
|||
),
|
||||
&[
|
||||
#field.to_account_info(),
|
||||
system_program.clone(),
|
||||
system_program.to_account_info(),
|
||||
],
|
||||
&[#seeds_with_nonce],
|
||||
)?;
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use crate::program_codegen::dispatch;
|
||||
use crate::Program;
|
||||
use heck::CamelCase;
|
||||
use quote::quote;
|
||||
|
||||
pub fn generate(program: &Program) -> proc_macro2::TokenStream {
|
||||
let name: proc_macro2::TokenStream = program.name.to_string().to_camel_case().parse().unwrap();
|
||||
let fallback_maybe = dispatch::gen_fallback(program).unwrap_or(quote! {
|
||||
Err(anchor_lang::__private::ErrorCode::InstructionMissing.into());
|
||||
});
|
||||
|
@ -65,5 +67,29 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
|
|||
e
|
||||
})
|
||||
}
|
||||
|
||||
pub mod program {
|
||||
use super::*;
|
||||
|
||||
/// Type representing the program.
|
||||
#[derive(Clone)]
|
||||
pub struct #name;
|
||||
|
||||
impl anchor_lang::AccountDeserialize for #name {
|
||||
fn try_deserialize(buf: &mut &[u8]) -> std::result::Result<Self, anchor_lang::solana_program::program_error::ProgramError> {
|
||||
#name::try_deserialize_unchecked(buf)
|
||||
}
|
||||
|
||||
fn try_deserialize_unchecked(_buf: &mut &[u8]) -> std::result::Result<Self, anchor_lang::solana_program::program_error::ProgramError> {
|
||||
Ok(#name)
|
||||
}
|
||||
}
|
||||
|
||||
impl anchor_lang::Id for #name {
|
||||
fn id() -> Pubkey {
|
||||
ID
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -178,6 +178,9 @@ impl Field {
|
|||
Ty::AccountInfo => quote! {
|
||||
AccountInfo
|
||||
},
|
||||
Ty::Signer => quote! {
|
||||
Signer
|
||||
},
|
||||
Ty::Account(AccountTy { boxed, .. }) => {
|
||||
if *boxed {
|
||||
quote! {
|
||||
|
@ -271,7 +274,9 @@ impl Field {
|
|||
Ty::Sysvar(_) => quote! { anchor_lang::Sysvar },
|
||||
Ty::CpiState(_) => quote! { anchor_lang::CpiState },
|
||||
Ty::ProgramState(_) => quote! { anchor_lang::ProgramState },
|
||||
Ty::Program(_) => quote! { anchor_lang::Program },
|
||||
Ty::AccountInfo => quote! {},
|
||||
Ty::Signer => quote! {},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,6 +286,9 @@ impl Field {
|
|||
Ty::AccountInfo => quote! {
|
||||
AccountInfo
|
||||
},
|
||||
Ty::Signer => quote! {
|
||||
Signer
|
||||
},
|
||||
Ty::ProgramAccount(ty) => {
|
||||
let ident = &ty.account_type_path;
|
||||
quote! {
|
||||
|
@ -329,6 +337,12 @@ impl Field {
|
|||
SysvarTy::Instructions => quote! {Instructions},
|
||||
SysvarTy::Rewards => quote! {Rewards},
|
||||
},
|
||||
Ty::Program(ty) => {
|
||||
let program = &ty.account_type_path;
|
||||
quote! {
|
||||
#program
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -353,6 +367,8 @@ pub enum Ty {
|
|||
CpiAccount(CpiAccountTy),
|
||||
Sysvar(SysvarTy),
|
||||
Account(AccountTy),
|
||||
Program(ProgramTy),
|
||||
Signer,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
@ -405,6 +421,12 @@ pub struct AccountTy {
|
|||
pub boxed: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ProgramTy {
|
||||
// The struct type of the account.
|
||||
pub account_type_path: TypePath,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
pub name: String,
|
||||
|
|
|
@ -74,6 +74,8 @@ fn is_field_primitive(f: &syn::Field) -> ParseResult<bool> {
|
|||
| "CpiState"
|
||||
| "Loader"
|
||||
| "Account"
|
||||
| "Program"
|
||||
| "Signer"
|
||||
);
|
||||
Ok(r)
|
||||
}
|
||||
|
@ -92,6 +94,8 @@ fn parse_ty(f: &syn::Field) -> ParseResult<Ty> {
|
|||
"AccountInfo" => Ty::AccountInfo,
|
||||
"Loader" => Ty::Loader(parse_program_account_zero_copy(&path)?),
|
||||
"Account" => Ty::Account(parse_account_ty(&path)?),
|
||||
"Program" => Ty::Program(parse_program_ty(&path)?),
|
||||
"Signer" => Ty::Signer,
|
||||
_ => return Err(ParseError::new(f.ty.span(), "invalid account type given")),
|
||||
};
|
||||
|
||||
|
@ -167,6 +171,11 @@ fn parse_account_ty(path: &syn::Path) -> ParseResult<AccountTy> {
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_program_ty(path: &syn::Path) -> ParseResult<ProgramTy> {
|
||||
let account_type_path = parse_account(path)?;
|
||||
Ok(ProgramTy { account_type_path })
|
||||
}
|
||||
|
||||
// TODO: this whole method is a hack. Do something more idiomatic.
|
||||
fn parse_account(mut path: &syn::Path) -> ParseResult<syn::TypePath> {
|
||||
if parser::tts_to_string(path)
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
use anchor_lang::solana_program::account_info::AccountInfo;
|
||||
use anchor_lang::solana_program::entrypoint::ProgramResult;
|
||||
use anchor_lang::solana_program::program_error::ProgramError;
|
||||
use anchor_lang::solana_program::pubkey::Pubkey;
|
||||
use anchor_lang::{Accounts, CpiContext, ToAccountInfos};
|
||||
use serum_dex::instruction::SelfTradeBehavior;
|
||||
use serum_dex::matching::{OrderType, Side};
|
||||
use std::io::Write;
|
||||
use std::num::NonZeroU64;
|
||||
|
||||
#[cfg(not(feature = "devnet"))]
|
||||
|
@ -280,3 +283,29 @@ pub struct InitializeMarket<'info> {
|
|||
pub event_q: AccountInfo<'info>,
|
||||
pub rent: AccountInfo<'info>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Dex;
|
||||
|
||||
impl anchor_lang::AccountDeserialize for Dex {
|
||||
fn try_deserialize(buf: &mut &[u8]) -> Result<Self, ProgramError> {
|
||||
Dex::try_deserialize_unchecked(buf)
|
||||
}
|
||||
|
||||
fn try_deserialize_unchecked(_buf: &mut &[u8]) -> Result<Self, ProgramError> {
|
||||
Ok(Dex)
|
||||
}
|
||||
}
|
||||
|
||||
impl anchor_lang::AccountSerialize for Dex {
|
||||
fn try_serialize<W: Write>(&self, _writer: &mut W) -> Result<(), ProgramError> {
|
||||
// no-op
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl anchor_lang::Id for Dex {
|
||||
fn id() -> Pubkey {
|
||||
ID
|
||||
}
|
||||
}
|
||||
|
|
|
@ -305,6 +305,25 @@ impl Deref for Mint {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Token;
|
||||
|
||||
impl anchor_lang::AccountDeserialize for Token {
|
||||
fn try_deserialize(buf: &mut &[u8]) -> Result<Self, ProgramError> {
|
||||
Token::try_deserialize_unchecked(buf)
|
||||
}
|
||||
|
||||
fn try_deserialize_unchecked(_buf: &mut &[u8]) -> Result<Self, ProgramError> {
|
||||
Ok(Token)
|
||||
}
|
||||
}
|
||||
|
||||
impl anchor_lang::Id for Token {
|
||||
fn id() -> Pubkey {
|
||||
ID
|
||||
}
|
||||
}
|
||||
|
||||
// Field parsers to save compute. All account validation is assumed to be done
|
||||
// outside of these methods.
|
||||
pub mod accessor {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 9a257678dfd0bda0c222e516e8c1a778b401d71e
|
||||
Subproject commit 28a7f1e0c134f16f99e201069970df78ec5d7e78
|
|
@ -1,12 +1,15 @@
|
|||
// WIP. This program has been checkpointed and is not production ready.
|
||||
|
||||
use anchor_lang::prelude::*;
|
||||
use anchor_lang::solana_program::system_program;
|
||||
use anchor_lang::solana_program::sysvar::instructions as tx_instructions;
|
||||
use anchor_spl::token::{self, Mint, TokenAccount};
|
||||
use anchor_spl::{dex, mint};
|
||||
use anchor_spl::dex::{self, Dex};
|
||||
use anchor_spl::mint;
|
||||
use anchor_spl::token::{self, Mint, Token, TokenAccount};
|
||||
use lockup::program::Lockup;
|
||||
use registry::program::Registry;
|
||||
use registry::{Registrar, RewardVendorKind};
|
||||
use std::convert::TryInto;
|
||||
use swap::program::Swap;
|
||||
|
||||
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
||||
|
||||
|
@ -29,7 +32,7 @@ pub mod cfo {
|
|||
let officer = &mut ctx.accounts.officer;
|
||||
officer.authority = *ctx.accounts.authority.key;
|
||||
officer.swap_program = *ctx.accounts.swap_program.key;
|
||||
officer.dex_program = *ctx.accounts.dex_program.key;
|
||||
officer.dex_program = ctx.accounts.dex_program.key();
|
||||
officer.distribution = d;
|
||||
officer.registrar = registrar;
|
||||
officer.msrm_registrar = msrm_registrar;
|
||||
|
@ -333,21 +336,16 @@ pub struct CreateOfficer<'info> {
|
|||
token::authority = officer,
|
||||
)]
|
||||
treasury: Box<Account<'info, TokenAccount>>,
|
||||
#[account(signer)]
|
||||
authority: AccountInfo<'info>,
|
||||
#[cfg_attr(
|
||||
not(feature = "test"),
|
||||
account(address = mint::SRM),
|
||||
)]
|
||||
mint: AccountInfo<'info>,
|
||||
#[account(executable)]
|
||||
dex_program: AccountInfo<'info>,
|
||||
#[account(executable)]
|
||||
swap_program: AccountInfo<'info>,
|
||||
#[account(address = system_program::ID)]
|
||||
system_program: AccountInfo<'info>,
|
||||
#[account(address = spl_token::ID)]
|
||||
token_program: AccountInfo<'info>,
|
||||
mint: Box<Account<'info, Mint>>,
|
||||
dex_program: Program<'info, Dex>,
|
||||
swap_program: Program<'info, Swap>,
|
||||
system_program: Program<'info, System>,
|
||||
token_program: Program<'info, Token>,
|
||||
rent: Sysvar<'info, Rent>,
|
||||
}
|
||||
|
||||
|
@ -366,12 +364,10 @@ pub struct CreateOfficerToken<'info> {
|
|||
token: Account<'info, TokenAccount>,
|
||||
#[account(owner = spl_token::ID)]
|
||||
mint: AccountInfo<'info>,
|
||||
#[account(mut, signer)]
|
||||
payer: AccountInfo<'info>,
|
||||
#[account(address = system_program::ID)]
|
||||
system_program: AccountInfo<'info>,
|
||||
#[account(address = spl_token::ID)]
|
||||
token_program: AccountInfo<'info>,
|
||||
#[account(mut)]
|
||||
payer: Signer<'info>,
|
||||
system_program: Program<'info, System>,
|
||||
token_program: Program<'info, Token>,
|
||||
rent: Sysvar<'info, Rent>,
|
||||
}
|
||||
|
||||
|
@ -379,8 +375,7 @@ pub struct CreateOfficerToken<'info> {
|
|||
pub struct SetDistribution<'info> {
|
||||
#[account(has_one = authority)]
|
||||
officer: Account<'info, Officer>,
|
||||
#[account(signer)]
|
||||
authority: AccountInfo<'info>,
|
||||
authority: Signer<'info>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
|
@ -398,26 +393,25 @@ pub struct SweepFees<'info> {
|
|||
)]
|
||||
sweep_vault: Account<'info, TokenAccount>,
|
||||
mint: AccountInfo<'info>,
|
||||
dex: Dex<'info>,
|
||||
dex: DexAccounts<'info>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct Dex<'info> {
|
||||
pub struct DexAccounts<'info> {
|
||||
#[account(mut)]
|
||||
market: AccountInfo<'info>,
|
||||
#[account(mut)]
|
||||
pc_vault: AccountInfo<'info>,
|
||||
sweep_authority: AccountInfo<'info>,
|
||||
vault_signer: AccountInfo<'info>,
|
||||
dex_program: AccountInfo<'info>,
|
||||
#[account(address = spl_token::ID)]
|
||||
token_program: AccountInfo<'info>,
|
||||
dex_program: Program<'info, Dex>,
|
||||
token_program: Program<'info, Token>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct SwapToUsdc<'info> {
|
||||
#[account(
|
||||
seeds = [dex_program.key().as_ref()],
|
||||
seeds = [dex_program.key.as_ref()],
|
||||
bump = officer.bumps.bump,
|
||||
)]
|
||||
officer: Account<'info, Officer>,
|
||||
|
@ -432,12 +426,9 @@ pub struct SwapToUsdc<'info> {
|
|||
quote_vault: AccountInfo<'info>,
|
||||
#[account(seeds = [officer.key().as_ref(), mint::USDC.as_ref()], bump)]
|
||||
usdc_vault: AccountInfo<'info>,
|
||||
#[account(address = swap::ID)]
|
||||
swap_program: AccountInfo<'info>,
|
||||
#[account(address = dex::ID)]
|
||||
dex_program: AccountInfo<'info>,
|
||||
#[account(address = token::ID)]
|
||||
token_program: AccountInfo<'info>,
|
||||
swap_program: Program<'info, Swap>,
|
||||
dex_program: Program<'info, Dex>,
|
||||
token_program: Program<'info, Token>,
|
||||
#[account(address = tx_instructions::ID)]
|
||||
instructions: AccountInfo<'info>,
|
||||
rent: Sysvar<'info, Rent>,
|
||||
|
@ -446,7 +437,7 @@ pub struct SwapToUsdc<'info> {
|
|||
#[derive(Accounts)]
|
||||
pub struct SwapToSrm<'info> {
|
||||
#[account(
|
||||
seeds = [dex_program.key().as_ref()],
|
||||
seeds = [dex_program.key.as_ref()],
|
||||
bump = officer.bumps.bump,
|
||||
)]
|
||||
officer: Account<'info, Officer>,
|
||||
|
@ -466,12 +457,9 @@ pub struct SwapToSrm<'info> {
|
|||
constraint = &officer.stake != from_vault.key,
|
||||
)]
|
||||
srm_vault: AccountInfo<'info>,
|
||||
#[account(address = swap::ID)]
|
||||
swap_program: AccountInfo<'info>,
|
||||
#[account(address = dex::ID)]
|
||||
dex_program: AccountInfo<'info>,
|
||||
#[account(address = token::ID)]
|
||||
token_program: AccountInfo<'info>,
|
||||
swap_program: Program<'info, Swap>,
|
||||
dex_program: Program<'info, Dex>,
|
||||
token_program: Program<'info, Token>,
|
||||
#[account(address = tx_instructions::ID)]
|
||||
instructions: AccountInfo<'info>,
|
||||
rent: Sysvar<'info, Rent>,
|
||||
|
@ -522,10 +510,8 @@ pub struct Distribute<'info> {
|
|||
srm_vault: Account<'info, TokenAccount>,
|
||||
#[account(address = mint::SRM)]
|
||||
mint: AccountInfo<'info>,
|
||||
#[account(address = spl_token::ID)]
|
||||
token_program: AccountInfo<'info>,
|
||||
#[account(address = dex::ID)]
|
||||
dex_program: AccountInfo<'info>,
|
||||
token_program: Program<'info, Token>,
|
||||
dex_program: Program<'info, Dex>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
|
@ -548,16 +534,11 @@ pub struct DropStakeReward<'info> {
|
|||
mint: AccountInfo<'info>,
|
||||
srm: DropStakeRewardPool<'info>,
|
||||
msrm: DropStakeRewardPool<'info>,
|
||||
#[account(owner = *registry_program.key)]
|
||||
msrm_registrar: Box<Account<'info, Registrar>>,
|
||||
#[account(address = token::ID)]
|
||||
token_program: AccountInfo<'info>,
|
||||
#[account(address = registry::ID)]
|
||||
registry_program: AccountInfo<'info>,
|
||||
#[account(address = lockup::ID)]
|
||||
lockup_program: AccountInfo<'info>,
|
||||
#[account(address = dex::ID)]
|
||||
dex_program: AccountInfo<'info>,
|
||||
token_program: Program<'info, Token>,
|
||||
registry_program: Program<'info, Registry>,
|
||||
lockup_program: Program<'info, Lockup>,
|
||||
dex_program: Program<'info, Dex>,
|
||||
clock: Sysvar<'info, Clock>,
|
||||
rent: Sysvar<'info, Rent>,
|
||||
}
|
||||
|
@ -628,7 +609,7 @@ impl<'info> From<&SweepFees<'info>> for CpiContext<'_, '_, '_, 'info, dex::Sweep
|
|||
vault_signer: sweep.dex.vault_signer.to_account_info(),
|
||||
token_program: sweep.dex.token_program.to_account_info(),
|
||||
};
|
||||
CpiContext::new(program, accounts)
|
||||
CpiContext::new(program.to_account_info(), accounts)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -655,7 +636,7 @@ impl<'info> From<&SwapToSrm<'info>> for CpiContext<'_, '_, '_, 'info, swap::Swap
|
|||
token_program: accs.token_program.to_account_info(),
|
||||
rent: accs.rent.to_account_info(),
|
||||
};
|
||||
CpiContext::new(program, accounts)
|
||||
CpiContext::new(program.to_account_info(), accounts)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -682,7 +663,7 @@ impl<'info> From<&SwapToUsdc<'info>> for CpiContext<'_, '_, '_, 'info, swap::Swa
|
|||
token_program: accs.token_program.to_account_info(),
|
||||
rent: accs.rent.to_account_info(),
|
||||
};
|
||||
CpiContext::new(program, accounts)
|
||||
CpiContext::new(program.to_account_info(), accounts)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -694,7 +675,7 @@ impl<'info> From<&Distribute<'info>> for CpiContext<'_, '_, '_, 'info, token::Bu
|
|||
to: accs.srm_vault.to_account_info(),
|
||||
authority: accs.officer.to_account_info(),
|
||||
};
|
||||
CpiContext::new(program, accounts)
|
||||
CpiContext::new(program.to_account_info(), accounts)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -710,11 +691,11 @@ impl<'info> DropStakeReward<'info> {
|
|||
vendor_vault: CpiAccount::try_from(&self.srm.vendor_vault).unwrap(),
|
||||
depositor: self.stake.to_account_info(),
|
||||
depositor_authority: self.officer.to_account_info(),
|
||||
token_program: self.token_program.clone(),
|
||||
token_program: self.token_program.to_account_info(),
|
||||
clock: self.clock.clone(),
|
||||
rent: self.rent.clone(),
|
||||
};
|
||||
CpiContext::new(program, accounts)
|
||||
CpiContext::new(program.to_account_info(), accounts)
|
||||
}
|
||||
|
||||
fn into_msrm_reward(&self) -> CpiContext<'_, '_, '_, 'info, registry::DropReward<'info>> {
|
||||
|
@ -728,43 +709,43 @@ impl<'info> DropStakeReward<'info> {
|
|||
vendor_vault: CpiAccount::try_from(&self.msrm.vendor_vault).unwrap(),
|
||||
depositor: self.stake.to_account_info(),
|
||||
depositor_authority: self.officer.to_account_info(),
|
||||
token_program: self.token_program.clone(),
|
||||
token_program: self.token_program.to_account_info(),
|
||||
clock: self.clock.clone(),
|
||||
rent: self.rent.clone(),
|
||||
};
|
||||
CpiContext::new(program, accounts)
|
||||
CpiContext::new(program.to_account_info(), accounts)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'info> Distribute<'info> {
|
||||
fn into_burn(&self) -> CpiContext<'_, '_, '_, 'info, token::Burn<'info>> {
|
||||
let program = self.token_program.clone();
|
||||
let program = self.token_program.to_account_info();
|
||||
let accounts = token::Burn {
|
||||
mint: self.mint.clone(),
|
||||
to: self.srm_vault.to_account_info(),
|
||||
authority: self.officer.to_account_info(),
|
||||
};
|
||||
CpiContext::new(program, accounts)
|
||||
CpiContext::new(program.to_account_info(), accounts)
|
||||
}
|
||||
|
||||
fn into_stake_transfer(&self) -> CpiContext<'_, '_, '_, 'info, token::Transfer<'info>> {
|
||||
let program = self.token_program.clone();
|
||||
let program = self.token_program.to_account_info();
|
||||
let accounts = token::Transfer {
|
||||
from: self.srm_vault.to_account_info(),
|
||||
to: self.stake.to_account_info(),
|
||||
authority: self.officer.to_account_info(),
|
||||
};
|
||||
CpiContext::new(program, accounts)
|
||||
CpiContext::new(program.to_account_info(), accounts)
|
||||
}
|
||||
|
||||
fn into_treasury_transfer(&self) -> CpiContext<'_, '_, '_, 'info, token::Transfer<'info>> {
|
||||
let program = self.token_program.clone();
|
||||
let program = self.token_program.to_account_info();
|
||||
let accounts = token::Transfer {
|
||||
from: self.srm_vault.to_account_info(),
|
||||
to: self.treasury.to_account_info(),
|
||||
authority: self.officer.to_account_info(),
|
||||
};
|
||||
CpiContext::new(program, accounts)
|
||||
CpiContext::new(program.to_account_info(), accounts)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//! it's suggested to start with the other examples.
|
||||
|
||||
use anchor_lang::prelude::*;
|
||||
use anchor_lang::solana_program;
|
||||
use anchor_lang::solana_program::instruction::Instruction;
|
||||
use anchor_lang::solana_program::program;
|
||||
use anchor_spl::token::{self, TokenAccount, Transfer};
|
||||
|
||||
mod calculator;
|
||||
|
@ -477,7 +477,8 @@ pub fn whitelist_relay_cpi<'info>(
|
|||
let signer = &[&seeds[..]];
|
||||
let mut accounts = transfer.to_account_infos();
|
||||
accounts.extend_from_slice(&remaining_accounts);
|
||||
program::invoke_signed(&relay_instruction, &accounts, signer).map_err(Into::into)
|
||||
solana_program::program::invoke_signed(&relay_instruction, &accounts, signer)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn is_whitelisted<'info>(transfer: &WhitelistTransfer<'info>) -> Result<()> {
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
cluster = "localnet"
|
||||
wallet = "~/.config/solana/id.json"
|
||||
|
||||
[programs.localnet]
|
||||
permissioned_markets = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
|
||||
permissioned_markets_middleware = "HmbTLCmaGvZhKnn1Zfa1JVnp7vkMV4DYVxPLWBVoN65L"
|
||||
|
||||
[[test.genesis]]
|
||||
address = "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin"
|
||||
program = "./deps/serum-dex/dex/target/deploy/serum_dex.so"
|
||||
|
|
|
@ -10,6 +10,8 @@ use solana_program::entrypoint::ProgramResult;
|
|||
use solana_program::pubkey::Pubkey;
|
||||
use solana_program::sysvar::rent;
|
||||
|
||||
declare_id!("HmbTLCmaGvZhKnn1Zfa1JVnp7vkMV4DYVxPLWBVoN65L");
|
||||
|
||||
/// # Permissioned Markets
|
||||
///
|
||||
/// This demonstrates how to create "permissioned markets" on Serum via a proxy.
|
||||
|
|
|
@ -6,11 +6,12 @@ use serum_dex::instruction::MarketInstruction;
|
|||
use serum_dex::matching::Side;
|
||||
use serum_dex::state::OpenOrders;
|
||||
use solana_program::instruction::Instruction;
|
||||
use solana_program::program;
|
||||
use solana_program::system_program;
|
||||
use solana_program::sysvar::rent;
|
||||
use std::mem::size_of;
|
||||
|
||||
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
||||
|
||||
/// A low level example of permissioned markets.
|
||||
///
|
||||
/// It's recommended to instead study `programs/permissioned-markets-middleware`
|
||||
|
@ -262,7 +263,7 @@ pub mod permissioned_markets {
|
|||
})
|
||||
.collect();
|
||||
let signers: Vec<&[&[u8]]> = tmp_signers.iter().map(|seeds| &seeds[..]).collect();
|
||||
program::invoke_signed(&ix, &accounts, &signers)?;
|
||||
solana_program::program::invoke_signed(&ix, &accounts, &signers)?;
|
||||
}
|
||||
|
||||
// CPI to the dex.
|
||||
|
@ -290,7 +291,7 @@ pub mod permissioned_markets {
|
|||
dex_program = dex.key,
|
||||
market = market
|
||||
};
|
||||
program::invoke_signed(&ix, &acc_infos, &[seeds, seeds_init])?;
|
||||
solana_program::program::invoke_signed(&ix, &acc_infos, &[seeds, seeds_init])?;
|
||||
|
||||
// Execute post instruction.
|
||||
if let Some((ix, accounts, seeds)) = post_instruction {
|
||||
|
@ -302,7 +303,7 @@ pub mod permissioned_markets {
|
|||
})
|
||||
.collect();
|
||||
let signers: Vec<&[&[u8]]> = tmp_signers.iter().map(|seeds| &seeds[..]).collect();
|
||||
program::invoke_signed(&ix, &accounts, &signers)?;
|
||||
solana_program::program::invoke_signed(&ix, &accounts, &signers)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -2,5 +2,8 @@
|
|||
cluster = "localnet"
|
||||
wallet = "~/.config/solana/id.json"
|
||||
|
||||
[programs.localnet]
|
||||
pyth = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
|
||||
|
||||
[scripts]
|
||||
test = "ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
|
||||
|
|
|
@ -2,6 +2,8 @@ use anchor_lang::prelude::*;
|
|||
mod pc;
|
||||
use pc::Price;
|
||||
|
||||
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
||||
|
||||
#[program]
|
||||
pub mod pyth {
|
||||
use super::*;
|
||||
|
|
|
@ -2,5 +2,8 @@
|
|||
cluster = "localnet"
|
||||
wallet = "~/.config/solana/id.json"
|
||||
|
||||
[programs.localnet]
|
||||
token_proxy = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
|
||||
|
||||
[scripts]
|
||||
test = "mocha -t 1000000 tests/"
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use anchor_spl::token::{self, Burn, MintTo, SetAuthority, Transfer};
|
||||
|
||||
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
||||
|
||||
#[program]
|
||||
mod token_proxy {
|
||||
use super::*;
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
cluster = "localnet"
|
||||
wallet = "~/.config/solana/id.json"
|
||||
|
||||
[programs.localnet]
|
||||
swap = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
|
||||
|
||||
[[test.genesis]]
|
||||
address = "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin"
|
||||
program = "./deps/serum-dex/dex/target/deploy/serum_dex.so"
|
||||
|
|
|
@ -14,6 +14,8 @@ use anchor_spl::dex::serum_dex::state::MarketState;
|
|||
use anchor_spl::token;
|
||||
use std::num::NonZeroU64;
|
||||
|
||||
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
||||
|
||||
#[program]
|
||||
pub mod swap {
|
||||
use super::*;
|
||||
|
|
|
@ -2,5 +2,8 @@
|
|||
cluster = "localnet"
|
||||
wallet = "~/.config/solana/id.json"
|
||||
|
||||
[programs.localnet]
|
||||
sysvars = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
|
||||
|
||||
[scripts]
|
||||
test = "mocha -t 1000000 tests/"
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
||||
|
||||
#[program]
|
||||
mod sysvars {
|
||||
use super::*;
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
cluster = "localnet"
|
||||
wallet = "~/.config/solana/id.json"
|
||||
|
||||
[programs.localnet]
|
||||
typescript = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
|
||||
|
||||
[workspace]
|
||||
members = ["programs/typescript"]
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
use anchor_lang::prelude::*;
|
||||
|
||||
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
|
||||
|
||||
#[program]
|
||||
pub mod typescript {
|
||||
use super::*;
|
||||
|
|
|
@ -80,6 +80,8 @@ const LangErrorCode = {
|
|||
AccountNotEnoughKeys: 165,
|
||||
AccountNotMutable: 166,
|
||||
AccountNotProgramOwned: 167,
|
||||
InvalidProgramId: 168,
|
||||
InvalidProgramIdExecutable: 169,
|
||||
|
||||
// State.
|
||||
StateInvalidAddress: 180,
|
||||
|
@ -159,6 +161,11 @@ const LangErrorMessage = new Map([
|
|||
LangErrorCode.AccountNotProgramOwned,
|
||||
"The given account is not owned by the executing program",
|
||||
],
|
||||
[LangErrorCode.InvalidProgramId, "Program ID was not as expected"],
|
||||
[
|
||||
LangErrorCode.InvalidProgramIdExecutable,
|
||||
"Program account is not executable",
|
||||
],
|
||||
|
||||
// State.
|
||||
[
|
||||
|
|
Loading…
Reference in New Issue