-
Notifications
You must be signed in to change notification settings - Fork 1.9k
lang: Allow CPI return values #1598
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3190bae
c707d92
e37a325
c4079c4
ee380b2
7b50f25
194308c
177b9ad
9c85dd6
552c49d
03b5d26
63a6a15
951838d
3aa7f94
6f3a86a
dbb65f0
497245e
5c9650b
88aafe6
3eaf8fe
3eec70b
1a65dd2
b0abf61
eaea067
a3b0c77
8be3da6
2cf9be7
c0427b8
e8593b2
fd40f59
83d0e7c
b49bf6c
50b8f00
9b14549
594cf4d
f16c155
82f70e3
93f6478
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| use crate::parser::program::ctx_accounts_ident; | ||
| use crate::{FallbackFn, Ix, IxArg}; | ||
| use crate::{FallbackFn, Ix, IxArg, IxReturn}; | ||
| use syn::parse::{Error as ParseError, Result as ParseResult}; | ||
| use syn::spanned::Spanned; | ||
|
|
||
|
|
@@ -23,12 +23,14 @@ pub fn parse(program_mod: &syn::ItemMod) -> ParseResult<(Vec<Ix>, Option<Fallbac | |
| }) | ||
| .map(|method: &syn::ItemFn| { | ||
| let (ctx, args) = parse_args(method)?; | ||
| let returns = parse_return(method)?; | ||
| let anchor_ident = ctx_accounts_ident(&ctx.raw_arg)?; | ||
| Ok(Ix { | ||
| raw_method: method.clone(), | ||
| ident: method.sig.ident.clone(), | ||
| args, | ||
| anchor_ident, | ||
| returns, | ||
| }) | ||
| }) | ||
| .collect::<ParseResult<Vec<Ix>>>()?; | ||
|
|
@@ -91,3 +93,34 @@ pub fn parse_args(method: &syn::ItemFn) -> ParseResult<(IxArg, Vec<IxArg>)> { | |
|
|
||
| Ok((ctx, args)) | ||
| } | ||
|
|
||
| pub fn parse_return(method: &syn::ItemFn) -> ParseResult<IxReturn> { | ||
| match method.sig.output { | ||
| syn::ReturnType::Type(_, ref ty) => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. an error here would be nice that hardcodes (with the return code (and possibly even other code) depends on this exact return type and you can't use aliases like
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is still some tests returning
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yea I cant think of anything that can actually go wrong with your code defaulting to no return type. so no need for that extra check i think |
||
| let ty = match ty.as_ref() { | ||
| syn::Type::Path(ty) => ty, | ||
| _ => return Err(ParseError::new(ty.span(), "expected a return type")), | ||
| }; | ||
| // Assume unit return by default | ||
| let default_generic_arg = syn::GenericArgument::Type(syn::parse_str("()").unwrap()); | ||
| let generic_args = match &ty.path.segments.last().unwrap().arguments { | ||
| syn::PathArguments::AngleBracketed(params) => params.args.iter().last().unwrap(), | ||
| _ => &default_generic_arg, | ||
| }; | ||
| let ty = match generic_args { | ||
| syn::GenericArgument::Type(ty) => ty.clone(), | ||
| _ => { | ||
| return Err(ParseError::new( | ||
| ty.span(), | ||
| "expected generic return type to be a type", | ||
| )) | ||
| } | ||
| }; | ||
| Ok(IxReturn { ty }) | ||
| } | ||
| _ => Err(ParseError::new( | ||
| method.sig.output.span(), | ||
| "expected a return type", | ||
| )), | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
|
|
||
| .anchor | ||
| .DS_Store | ||
| target | ||
| **/*.rs.bk | ||
| node_modules |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| [features] | ||
| seeds = false | ||
|
|
||
| [programs.localnet] | ||
| callee = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS" | ||
| caller = "HmbTLCmaGvZhKnn1Zfa1JVnp7vkMV4DYVxPLWBVoN65L" | ||
|
|
||
| [registry] | ||
| url = "https://anchor.projectserum.com" | ||
|
|
||
| [provider] | ||
| cluster = "localnet" | ||
| wallet = "~/.config/solana/id.json" | ||
|
|
||
| [scripts] | ||
| test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| [workspace] | ||
| members = [ | ||
| "programs/*" | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| // Migrations are an early feature. Currently, they're nothing more than this | ||
| // single deploy script that's invoked from the CLI, injecting a provider | ||
| // configured from the workspace's Anchor.toml. | ||
|
|
||
| const anchor = require("@project-serum/anchor"); | ||
|
|
||
| module.exports = async function (provider) { | ||
| // Configure client to use the provider. | ||
| anchor.setProvider(provider); | ||
|
|
||
| // Add your deploy script here. | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the way it works / what worked for me is that you dont have to specify the dependencies here. The
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea that is right |
||
| "name": "cpi-returns", | ||
| "version": "0.23.0", | ||
| "license": "(MIT OR Apache-2.0)", | ||
| "homepage": "https://github.com/project-serum/anchor#readme", | ||
| "bugs": { | ||
| "url": "https://github.com/project-serum/anchor/issues" | ||
| }, | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/project-serum/anchor.git" | ||
| }, | ||
| "engines": { | ||
| "node": ">=11" | ||
| }, | ||
| "scripts": { | ||
| "test": "anchor run test-with-build" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| [package] | ||
| name = "callee" | ||
| version = "0.1.0" | ||
| description = "Created with Anchor" | ||
| edition = "2018" | ||
|
|
||
| [lib] | ||
| crate-type = ["cdylib", "lib"] | ||
| name = "callee" | ||
|
|
||
| [features] | ||
| no-entrypoint = [] | ||
| no-idl = [] | ||
| no-log-ix-name = [] | ||
| cpi = ["no-entrypoint"] | ||
| default = [] | ||
|
|
||
| [dependencies] | ||
| anchor-lang = { path = "../../../../lang", features = ["init-if-needed"] } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| [target.bpfel-unknown-unknown.dependencies.std] | ||
| features = [] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| use anchor_lang::prelude::*; | ||
|
|
||
| declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"); | ||
|
|
||
| #[program] | ||
| pub mod callee { | ||
| use super::*; | ||
|
|
||
| #[derive(AnchorSerialize, AnchorDeserialize)] | ||
| pub struct StructReturn { | ||
| pub value: u64, | ||
| } | ||
|
|
||
| pub fn initialize(_ctx: Context<Initialize>) -> Result<()> { | ||
| Ok(()) | ||
| } | ||
|
|
||
| pub fn return_u64(_ctx: Context<CpiReturn>) -> Result<u64> { | ||
| Ok(10) | ||
| } | ||
|
|
||
| pub fn return_struct(_ctx: Context<CpiReturn>) -> Result<StructReturn> { | ||
| let s = StructReturn { value: 11 }; | ||
| Ok(s) | ||
| } | ||
|
tomlinton marked this conversation as resolved.
|
||
|
|
||
| pub fn return_vec(_ctx: Context<CpiReturn>) -> Result<Vec<u8>> { | ||
| Ok(vec![12, 13, 14, 100]) | ||
| } | ||
| } | ||
|
|
||
| #[derive(Accounts)] | ||
| pub struct Initialize<'info> { | ||
| #[account(init, payer = user, space = 8 + 8)] | ||
| pub account: Account<'info, CpiReturnAccount>, | ||
| #[account(mut)] | ||
| pub user: Signer<'info>, | ||
| pub system_program: Program<'info, System>, | ||
| } | ||
|
|
||
| #[derive(Accounts)] | ||
| pub struct CpiReturn<'info> { | ||
| #[account(mut)] | ||
| pub account: Account<'info, CpiReturnAccount>, | ||
| } | ||
|
|
||
| #[account] | ||
| pub struct CpiReturnAccount { | ||
|
tomlinton marked this conversation as resolved.
|
||
| pub value: u64, | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.