anchor_spl crate and example (#24)
This commit is contained in:
parent
b5ca210696
commit
11272e3677
|
@ -16,6 +16,9 @@ _examples: &examples
|
||||||
- nvm install $NODE_VERSION
|
- nvm install $NODE_VERSION
|
||||||
- npm install -g mocha
|
- npm install -g mocha
|
||||||
- npm install -g @project-serum/anchor
|
- npm install -g @project-serum/anchor
|
||||||
|
- npm install -g @project-serum/serum
|
||||||
|
- npm install -g @project-serum/common
|
||||||
|
- npm install -g @solana/spl-token
|
||||||
- sudo apt-get install -y pkg-config build-essential libudev-dev
|
- sudo apt-get install -y pkg-config build-essential libudev-dev
|
||||||
- sh -c "$(curl -sSfL https://release.solana.com/v1.5.0/install)"
|
- sh -c "$(curl -sSfL https://release.solana.com/v1.5.0/install)"
|
||||||
- export PATH="/home/travis/.local/share/solana/install/active_release/bin:$PATH"
|
- export PATH="/home/travis/.local/share/solana/install/active_release/bin:$PATH"
|
||||||
|
@ -42,6 +45,7 @@ jobs:
|
||||||
script:
|
script:
|
||||||
- pushd examples/sysvars && anchor test && popd
|
- pushd examples/sysvars && anchor test && popd
|
||||||
- pushd examples/composite && anchor test && popd
|
- pushd examples/composite && anchor test && popd
|
||||||
|
- pushd examples/spl/token-proxy && anchor test && popd
|
||||||
- pushd examples/tutorial/basic-0 && anchor test && popd
|
- pushd examples/tutorial/basic-0 && anchor test && popd
|
||||||
- pushd examples/tutorial/basic-1 && anchor test && popd
|
- pushd examples/tutorial/basic-1 && anchor test && popd
|
||||||
- pushd examples/tutorial/basic-2 && anchor test && popd
|
- pushd examples/tutorial/basic-2 && anchor test && popd
|
||||||
|
|
|
@ -121,6 +121,15 @@ dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anchor-spl"
|
||||||
|
version = "0.0.0-alpha.0"
|
||||||
|
dependencies = [
|
||||||
|
"anchor-lang",
|
||||||
|
"solana-program",
|
||||||
|
"spl-token 3.0.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anchor-syn"
|
name = "anchor-syn"
|
||||||
version = "0.0.0-alpha.0"
|
version = "0.0.0-alpha.0"
|
||||||
|
|
|
@ -27,4 +27,5 @@ members = [
|
||||||
"syn",
|
"syn",
|
||||||
"attribute/*",
|
"attribute/*",
|
||||||
"derive/*",
|
"derive/*",
|
||||||
|
"spl",
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
cluster = "localnet"
|
||||||
|
wallet = "~/.config/solana/id.json"
|
|
@ -0,0 +1,4 @@
|
||||||
|
[workspace]
|
||||||
|
members = [
|
||||||
|
"programs/*"
|
||||||
|
]
|
|
@ -0,0 +1,20 @@
|
||||||
|
[package]
|
||||||
|
name = "token-proxy"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Created with Anchor"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib", "lib"]
|
||||||
|
name = "token_proxy"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
no-entrypoint = []
|
||||||
|
cpi = ["no-entrypoint"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anchor-lang = { git = "https://github.com/project-serum/anchor", features = ["derive"] }
|
||||||
|
anchor-spl = { git = "https://github.com/project-serum/anchor", features = ["derive"] }
|
||||||
|
serum-borsh = { version = "0.8.0-serum.1", features = ["serum-program"] }
|
||||||
|
solana-program = "1.4.3"
|
||||||
|
solana-sdk = { version = "1.3.14", default-features = false, features = ["program"] }
|
|
@ -0,0 +1,2 @@
|
||||||
|
[target.bpfel-unknown-unknown.dependencies.std]
|
||||||
|
features = []
|
|
@ -0,0 +1,96 @@
|
||||||
|
//! This example demonstrates the use of the `anchor_spl::token` CPI client.
|
||||||
|
|
||||||
|
#![feature(proc_macro_hygiene)]
|
||||||
|
|
||||||
|
use anchor_lang::prelude::*;
|
||||||
|
use anchor_spl::token::{self, Burn, MintTo, Transfer};
|
||||||
|
|
||||||
|
#[program]
|
||||||
|
mod token_proxy {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub fn proxy_transfer(ctx: Context<ProxyTransfer>, amount: u64) -> ProgramResult {
|
||||||
|
token::transfer(ctx.accounts.into(), amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn proxy_mint_to(ctx: Context<ProxyMintTo>, amount: u64) -> ProgramResult {
|
||||||
|
token::mint_to(ctx.accounts.into(), amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn proxy_burn(ctx: Context<ProxyBurn>, amount: u64) -> ProgramResult {
|
||||||
|
token::burn(ctx.accounts.into(), amount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Accounts)]
|
||||||
|
pub struct ProxyTransfer<'info> {
|
||||||
|
#[account(signer)]
|
||||||
|
pub authority: AccountInfo<'info>,
|
||||||
|
#[account(mut)]
|
||||||
|
pub from: AccountInfo<'info>,
|
||||||
|
#[account(mut)]
|
||||||
|
pub to: AccountInfo<'info>,
|
||||||
|
pub token_program: AccountInfo<'info>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Accounts)]
|
||||||
|
pub struct ProxyMintTo<'info> {
|
||||||
|
#[account(signer)]
|
||||||
|
pub authority: AccountInfo<'info>,
|
||||||
|
#[account(mut)]
|
||||||
|
pub mint: AccountInfo<'info>,
|
||||||
|
#[account(mut)]
|
||||||
|
pub to: AccountInfo<'info>,
|
||||||
|
pub token_program: AccountInfo<'info>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Accounts)]
|
||||||
|
pub struct ProxyBurn<'info> {
|
||||||
|
#[account(signer)]
|
||||||
|
pub authority: AccountInfo<'info>,
|
||||||
|
#[account(mut)]
|
||||||
|
pub mint: AccountInfo<'info>,
|
||||||
|
#[account(mut)]
|
||||||
|
pub to: AccountInfo<'info>,
|
||||||
|
pub token_program: AccountInfo<'info>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'c, 'info> From<&mut ProxyTransfer<'info>>
|
||||||
|
for CpiContext<'a, 'b, 'c, 'info, Transfer<'info>>
|
||||||
|
{
|
||||||
|
fn from(accounts: &mut ProxyTransfer<'info>) -> CpiContext<'a, 'b, 'c, 'info, Transfer<'info>> {
|
||||||
|
let cpi_accounts = Transfer {
|
||||||
|
from: accounts.from.clone(),
|
||||||
|
to: accounts.to.clone(),
|
||||||
|
authority: accounts.authority.clone(),
|
||||||
|
};
|
||||||
|
let cpi_program = accounts.token_program.clone();
|
||||||
|
CpiContext::new(cpi_program, cpi_accounts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'c, 'info> From<&mut ProxyMintTo<'info>>
|
||||||
|
for CpiContext<'a, 'b, 'c, 'info, MintTo<'info>>
|
||||||
|
{
|
||||||
|
fn from(accounts: &mut ProxyMintTo<'info>) -> CpiContext<'a, 'b, 'c, 'info, MintTo<'info>> {
|
||||||
|
let cpi_accounts = MintTo {
|
||||||
|
mint: accounts.mint.clone(),
|
||||||
|
to: accounts.to.clone(),
|
||||||
|
authority: accounts.authority.clone(),
|
||||||
|
};
|
||||||
|
let cpi_program = accounts.token_program.clone();
|
||||||
|
CpiContext::new(cpi_program, cpi_accounts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'c, 'info> From<&mut ProxyBurn<'info>> for CpiContext<'a, 'b, 'c, 'info, Burn<'info>> {
|
||||||
|
fn from(accounts: &mut ProxyBurn<'info>) -> CpiContext<'a, 'b, 'c, 'info, Burn<'info>> {
|
||||||
|
let cpi_accounts = Burn {
|
||||||
|
mint: accounts.mint.clone(),
|
||||||
|
to: accounts.to.clone(),
|
||||||
|
authority: accounts.authority.clone(),
|
||||||
|
};
|
||||||
|
let cpi_program = accounts.token_program.clone();
|
||||||
|
CpiContext::new(cpi_program, cpi_accounts)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,150 @@
|
||||||
|
const anchor = require("@project-serum/anchor");
|
||||||
|
const assert = require("assert");
|
||||||
|
|
||||||
|
describe("token", () => {
|
||||||
|
const provider = anchor.Provider.local();
|
||||||
|
|
||||||
|
// Configure the client to use the local cluster.
|
||||||
|
anchor.setProvider(provider);
|
||||||
|
|
||||||
|
const program = anchor.workspace.TokenProxy;
|
||||||
|
|
||||||
|
let mint = null;
|
||||||
|
let from = null;
|
||||||
|
let to = null;
|
||||||
|
|
||||||
|
it("Initializes test state", async () => {
|
||||||
|
mint = await createMint(provider);
|
||||||
|
from = await createTokenAccount(provider, mint, provider.wallet.publicKey);
|
||||||
|
to = await createTokenAccount(provider, mint, provider.wallet.publicKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Mints a token", async () => {
|
||||||
|
await program.rpc.proxyMintTo(new anchor.BN(1000), {
|
||||||
|
accounts: {
|
||||||
|
authority: provider.wallet.publicKey,
|
||||||
|
mint,
|
||||||
|
to: from,
|
||||||
|
tokenProgram: TokenInstructions.TOKEN_PROGRAM_ID,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const fromAccount = await getTokenAccount(provider, from);
|
||||||
|
|
||||||
|
assert.ok(fromAccount.amount.eq(new anchor.BN(1000)));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Transfers a token", async () => {
|
||||||
|
await program.rpc.proxyTransfer(new anchor.BN(500), {
|
||||||
|
accounts: {
|
||||||
|
authority: provider.wallet.publicKey,
|
||||||
|
to,
|
||||||
|
from,
|
||||||
|
tokenProgram: TokenInstructions.TOKEN_PROGRAM_ID,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const fromAccount = await getTokenAccount(provider, from);
|
||||||
|
const toAccount = await getTokenAccount(provider, to);
|
||||||
|
|
||||||
|
assert.ok(fromAccount.amount.eq(new anchor.BN(500)));
|
||||||
|
assert.ok(fromAccount.amount.eq(new anchor.BN(500)));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Burns a token", async () => {
|
||||||
|
await program.rpc.proxyBurn(new anchor.BN(499), {
|
||||||
|
accounts: {
|
||||||
|
authority: provider.wallet.publicKey,
|
||||||
|
mint,
|
||||||
|
to,
|
||||||
|
tokenProgram: TokenInstructions.TOKEN_PROGRAM_ID,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const toAccount = await getTokenAccount(provider, to);
|
||||||
|
assert.ok(toAccount.amount.eq(new anchor.BN(1)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// SPL token client boilerplate for test initialization. Everything below here is
|
||||||
|
// mostly irrelevant to the point of the example.
|
||||||
|
|
||||||
|
const serumCmn = require("@project-serum/common");
|
||||||
|
const TokenInstructions = require("@project-serum/serum").TokenInstructions;
|
||||||
|
|
||||||
|
async function getTokenAccount(provider, addr) {
|
||||||
|
return await serumCmn.getTokenAccount(provider, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createMint(provider, authority) {
|
||||||
|
if (authority === undefined) {
|
||||||
|
authority = provider.wallet.publicKey;
|
||||||
|
}
|
||||||
|
const mint = new anchor.web3.Account();
|
||||||
|
const instructions = await createMintInstructions(
|
||||||
|
provider,
|
||||||
|
authority,
|
||||||
|
mint.publicKey
|
||||||
|
);
|
||||||
|
|
||||||
|
const tx = new anchor.web3.Transaction();
|
||||||
|
tx.add(...instructions);
|
||||||
|
|
||||||
|
await provider.send(tx, [mint]);
|
||||||
|
|
||||||
|
return mint.publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createMintInstructions(provider, authority, mint) {
|
||||||
|
let instructions = [
|
||||||
|
anchor.web3.SystemProgram.createAccount({
|
||||||
|
fromPubkey: provider.wallet.publicKey,
|
||||||
|
newAccountPubkey: mint,
|
||||||
|
space: 82,
|
||||||
|
lamports: await provider.connection.getMinimumBalanceForRentExemption(82),
|
||||||
|
programId: TokenInstructions.TOKEN_PROGRAM_ID,
|
||||||
|
}),
|
||||||
|
TokenInstructions.initializeMint({
|
||||||
|
mint,
|
||||||
|
decimals: 0,
|
||||||
|
mintAuthority: authority,
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
return instructions;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createTokenAccount(provider, mint, owner) {
|
||||||
|
const vault = new anchor.web3.Account();
|
||||||
|
const tx = new anchor.web3.Transaction();
|
||||||
|
tx.add(
|
||||||
|
...(await createTokenAccountInstrs(provider, vault.publicKey, mint, owner))
|
||||||
|
);
|
||||||
|
await provider.send(tx, [vault]);
|
||||||
|
return vault.publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createTokenAccountInstrs(
|
||||||
|
provider,
|
||||||
|
newAccountPubkey,
|
||||||
|
mint,
|
||||||
|
owner,
|
||||||
|
lamports
|
||||||
|
) {
|
||||||
|
if (lamports === undefined) {
|
||||||
|
lamports = await provider.connection.getMinimumBalanceForRentExemption(165);
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
anchor.web3.SystemProgram.createAccount({
|
||||||
|
fromPubkey: provider.wallet.publicKey,
|
||||||
|
newAccountPubkey,
|
||||||
|
space: 165,
|
||||||
|
lamports,
|
||||||
|
programId: TokenInstructions.TOKEN_PROGRAM_ID,
|
||||||
|
}),
|
||||||
|
TokenInstructions.initializeAccount({
|
||||||
|
account: newAccountPubkey,
|
||||||
|
mint,
|
||||||
|
owner,
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "anchor-spl"
|
||||||
|
version = "0.0.0-alpha.0"
|
||||||
|
authors = ["Armani Ferrante <armaniferrante@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anchor-lang = { path = "../", features = ["derive"] }
|
||||||
|
solana-program = "1.4.3"
|
||||||
|
spl-token = { version = "3.0.1", features = ["no-entrypoint"] }
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod token;
|
|
@ -0,0 +1,96 @@
|
||||||
|
use anchor_lang::{Accounts, CpiContext};
|
||||||
|
use solana_program::account_info::AccountInfo;
|
||||||
|
use solana_program::entrypoint::ProgramResult;
|
||||||
|
|
||||||
|
pub fn transfer<'a, 'b, 'c, 'info>(
|
||||||
|
ctx: CpiContext<'a, 'b, 'c, 'info, Transfer<'info>>,
|
||||||
|
amount: u64,
|
||||||
|
) -> ProgramResult {
|
||||||
|
let ix = spl_token::instruction::transfer(
|
||||||
|
&spl_token::ID,
|
||||||
|
ctx.accounts.from.key,
|
||||||
|
ctx.accounts.to.key,
|
||||||
|
ctx.accounts.authority.key,
|
||||||
|
&[],
|
||||||
|
amount,
|
||||||
|
)?;
|
||||||
|
solana_program::program::invoke_signed(
|
||||||
|
&ix,
|
||||||
|
&[
|
||||||
|
ctx.accounts.from.clone(),
|
||||||
|
ctx.accounts.to.clone(),
|
||||||
|
ctx.accounts.authority.clone(),
|
||||||
|
ctx.program.clone(),
|
||||||
|
],
|
||||||
|
ctx.signer_seeds,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mint_to<'a, 'b, 'c, 'info>(
|
||||||
|
ctx: CpiContext<'a, 'b, 'c, 'info, MintTo<'info>>,
|
||||||
|
amount: u64,
|
||||||
|
) -> ProgramResult {
|
||||||
|
let ix = spl_token::instruction::mint_to(
|
||||||
|
&spl_token::ID,
|
||||||
|
ctx.accounts.mint.key,
|
||||||
|
ctx.accounts.to.key,
|
||||||
|
ctx.accounts.authority.key,
|
||||||
|
&[],
|
||||||
|
amount,
|
||||||
|
)?;
|
||||||
|
solana_program::program::invoke_signed(
|
||||||
|
&ix,
|
||||||
|
&[
|
||||||
|
ctx.accounts.mint.clone(),
|
||||||
|
ctx.accounts.to.clone(),
|
||||||
|
ctx.accounts.authority.clone(),
|
||||||
|
ctx.program.clone(),
|
||||||
|
],
|
||||||
|
ctx.signer_seeds,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn burn<'a, 'b, 'c, 'info>(
|
||||||
|
ctx: CpiContext<'a, 'b, 'c, 'info, Burn<'info>>,
|
||||||
|
amount: u64,
|
||||||
|
) -> ProgramResult {
|
||||||
|
let ix = spl_token::instruction::burn(
|
||||||
|
&spl_token::ID,
|
||||||
|
ctx.accounts.to.key,
|
||||||
|
ctx.accounts.mint.key,
|
||||||
|
ctx.accounts.authority.key,
|
||||||
|
&[],
|
||||||
|
amount,
|
||||||
|
)?;
|
||||||
|
solana_program::program::invoke_signed(
|
||||||
|
&ix,
|
||||||
|
&[
|
||||||
|
ctx.accounts.to.clone(),
|
||||||
|
ctx.accounts.mint.clone(),
|
||||||
|
ctx.accounts.authority.clone(),
|
||||||
|
ctx.program.clone(),
|
||||||
|
],
|
||||||
|
ctx.signer_seeds,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Accounts)]
|
||||||
|
pub struct Transfer<'info> {
|
||||||
|
pub from: AccountInfo<'info>,
|
||||||
|
pub to: AccountInfo<'info>,
|
||||||
|
pub authority: AccountInfo<'info>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Accounts)]
|
||||||
|
pub struct MintTo<'info> {
|
||||||
|
pub mint: AccountInfo<'info>,
|
||||||
|
pub to: AccountInfo<'info>,
|
||||||
|
pub authority: AccountInfo<'info>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Accounts)]
|
||||||
|
pub struct Burn<'info> {
|
||||||
|
pub mint: AccountInfo<'info>,
|
||||||
|
pub to: AccountInfo<'info>,
|
||||||
|
pub authority: AccountInfo<'info>,
|
||||||
|
}
|
|
@ -76,7 +76,7 @@ where
|
||||||
T: AccountSerialize + AccountDeserialize + Clone,
|
T: AccountSerialize + AccountDeserialize + Clone,
|
||||||
{
|
{
|
||||||
fn try_accounts_init(
|
fn try_accounts_init(
|
||||||
program_id: &Pubkey,
|
_program_id: &Pubkey,
|
||||||
accounts: &mut &[AccountInfo<'info>],
|
accounts: &mut &[AccountInfo<'info>],
|
||||||
) -> Result<Self, ProgramError> {
|
) -> Result<Self, ProgramError> {
|
||||||
if accounts.len() == 0 {
|
if accounts.len() == 0 {
|
||||||
|
|
|
@ -81,7 +81,8 @@ pub fn generate(accs: AccountsStruct) -> proc_macro2::TokenStream {
|
||||||
AccountField::Field(f) => {
|
AccountField::Field(f) => {
|
||||||
let ident = &f.ident;
|
let ident = &f.ident;
|
||||||
let info = match f.ty {
|
let info = match f.ty {
|
||||||
Ty::AccountInfo => quote! { #ident },
|
// Only ProgramAccounts are automatically saved (when
|
||||||
|
// marked `#[account(mut)]`).
|
||||||
Ty::ProgramAccount(_) => quote! { #ident.to_account_info() },
|
Ty::ProgramAccount(_) => quote! { #ident.to_account_info() },
|
||||||
_ => return quote! {},
|
_ => return quote! {},
|
||||||
};
|
};
|
||||||
|
@ -144,8 +145,8 @@ pub fn generate(accs: AccountsStruct) -> proc_macro2::TokenStream {
|
||||||
};
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl#combined_generics Accounts#trait_generics for #name#strct_generics {
|
impl#combined_generics anchor_lang::Accounts#trait_generics for #name#strct_generics {
|
||||||
fn try_accounts(program_id: &Pubkey, accounts: &mut &[AccountInfo<'info>]) -> Result<Self, ProgramError> {
|
fn try_accounts(program_id: &solana_program::pubkey::Pubkey, accounts: &mut &[solana_program::account_info::AccountInfo<'info>]) -> Result<Self, solana_program::program_error::ProgramError> {
|
||||||
// Deserialize each account.
|
// Deserialize each account.
|
||||||
#(#deser_fields)*
|
#(#deser_fields)*
|
||||||
|
|
||||||
|
@ -159,8 +160,8 @@ pub fn generate(accs: AccountsStruct) -> proc_macro2::TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl#combined_generics ToAccountInfos#trait_generics for #name#strct_generics {
|
impl#combined_generics anchor_lang::ToAccountInfos#trait_generics for #name#strct_generics {
|
||||||
fn to_account_infos(&self) -> Vec<AccountInfo<'info>> {
|
fn to_account_infos(&self) -> Vec<solana_program::account_info::AccountInfo<'info>> {
|
||||||
let mut account_infos = vec![];
|
let mut account_infos = vec![];
|
||||||
|
|
||||||
#(#to_acc_infos)*
|
#(#to_acc_infos)*
|
||||||
|
@ -169,8 +170,8 @@ pub fn generate(accs: AccountsStruct) -> proc_macro2::TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl#combined_generics ToAccountMetas for #name#strct_generics {
|
impl#combined_generics anchor_lang::ToAccountMetas for #name#strct_generics {
|
||||||
fn to_account_metas(&self) -> Vec<AccountMeta> {
|
fn to_account_metas(&self) -> Vec<solana_program::instruction::AccountMeta> {
|
||||||
let mut account_metas = vec![];
|
let mut account_metas = vec![];
|
||||||
|
|
||||||
#(#to_acc_metas)*
|
#(#to_acc_metas)*
|
||||||
|
@ -181,7 +182,7 @@ pub fn generate(accs: AccountsStruct) -> proc_macro2::TokenStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl#strct_generics #name#strct_generics {
|
impl#strct_generics #name#strct_generics {
|
||||||
pub fn exit(&self, program_id: &Pubkey) -> ProgramResult {
|
pub fn exit(&self, program_id: &solana_program::pubkey::Pubkey) -> solana_program::entrypoint::ProgramResult {
|
||||||
#(#on_save)*
|
#(#on_save)*
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue