|
@@ -84,6 +84,12 @@ pub fn parse_token(stream: ParseStream) -> ParseResult<ConstraintToken> {
|
|
decimals: stream.parse()?,
|
|
decimals: stream.parse()?,
|
|
},
|
|
},
|
|
)),
|
|
)),
|
|
|
|
+ "token_program" => ConstraintToken::MintTokenProgram(Context::new(
|
|
|
|
+ span,
|
|
|
|
+ ConstraintTokenProgram {
|
|
|
|
+ token_program: stream.parse()?,
|
|
|
|
+ },
|
|
|
|
+ )),
|
|
_ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
|
|
_ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -111,6 +117,12 @@ pub fn parse_token(stream: ParseStream) -> ParseResult<ConstraintToken> {
|
|
auth: stream.parse()?,
|
|
auth: stream.parse()?,
|
|
},
|
|
},
|
|
)),
|
|
)),
|
|
|
|
+ "token_program" => ConstraintToken::TokenTokenProgram(Context::new(
|
|
|
|
+ span,
|
|
|
|
+ ConstraintTokenProgram {
|
|
|
|
+ token_program: stream.parse()?,
|
|
|
|
+ },
|
|
|
|
+ )),
|
|
_ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
|
|
_ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -138,6 +150,12 @@ pub fn parse_token(stream: ParseStream) -> ParseResult<ConstraintToken> {
|
|
auth: stream.parse()?,
|
|
auth: stream.parse()?,
|
|
},
|
|
},
|
|
)),
|
|
)),
|
|
|
|
+ "token_program" => ConstraintToken::AssociatedTokenTokenProgram(Context::new(
|
|
|
|
+ span,
|
|
|
|
+ ConstraintTokenProgram {
|
|
|
|
+ token_program: stream.parse()?,
|
|
|
|
+ },
|
|
|
|
+ )),
|
|
_ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
|
|
_ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -332,11 +350,14 @@ pub struct ConstraintGroupBuilder<'ty> {
|
|
pub address: Option<Context<ConstraintAddress>>,
|
|
pub address: Option<Context<ConstraintAddress>>,
|
|
pub token_mint: Option<Context<ConstraintTokenMint>>,
|
|
pub token_mint: Option<Context<ConstraintTokenMint>>,
|
|
pub token_authority: Option<Context<ConstraintTokenAuthority>>,
|
|
pub token_authority: Option<Context<ConstraintTokenAuthority>>,
|
|
|
|
+ pub token_token_program: Option<Context<ConstraintTokenProgram>>,
|
|
pub associated_token_mint: Option<Context<ConstraintTokenMint>>,
|
|
pub associated_token_mint: Option<Context<ConstraintTokenMint>>,
|
|
pub associated_token_authority: Option<Context<ConstraintTokenAuthority>>,
|
|
pub associated_token_authority: Option<Context<ConstraintTokenAuthority>>,
|
|
|
|
+ pub associated_token_token_program: Option<Context<ConstraintTokenProgram>>,
|
|
pub mint_authority: Option<Context<ConstraintMintAuthority>>,
|
|
pub mint_authority: Option<Context<ConstraintMintAuthority>>,
|
|
pub mint_freeze_authority: Option<Context<ConstraintMintFreezeAuthority>>,
|
|
pub mint_freeze_authority: Option<Context<ConstraintMintFreezeAuthority>>,
|
|
pub mint_decimals: Option<Context<ConstraintMintDecimals>>,
|
|
pub mint_decimals: Option<Context<ConstraintMintDecimals>>,
|
|
|
|
+ pub mint_token_program: Option<Context<ConstraintTokenProgram>>,
|
|
pub bump: Option<Context<ConstraintTokenBump>>,
|
|
pub bump: Option<Context<ConstraintTokenBump>>,
|
|
pub program_seed: Option<Context<ConstraintProgramSeed>>,
|
|
pub program_seed: Option<Context<ConstraintProgramSeed>>,
|
|
pub realloc: Option<Context<ConstraintRealloc>>,
|
|
pub realloc: Option<Context<ConstraintRealloc>>,
|
|
@@ -364,11 +385,14 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|
address: None,
|
|
address: None,
|
|
token_mint: None,
|
|
token_mint: None,
|
|
token_authority: None,
|
|
token_authority: None,
|
|
|
|
+ token_token_program: None,
|
|
associated_token_mint: None,
|
|
associated_token_mint: None,
|
|
associated_token_authority: None,
|
|
associated_token_authority: None,
|
|
|
|
+ associated_token_token_program: None,
|
|
mint_authority: None,
|
|
mint_authority: None,
|
|
mint_freeze_authority: None,
|
|
mint_freeze_authority: None,
|
|
mint_decimals: None,
|
|
mint_decimals: None,
|
|
|
|
+ mint_token_program: None,
|
|
bump: None,
|
|
bump: None,
|
|
program_seed: None,
|
|
program_seed: None,
|
|
realloc: None,
|
|
realloc: None,
|
|
@@ -563,11 +587,14 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|
address,
|
|
address,
|
|
token_mint,
|
|
token_mint,
|
|
token_authority,
|
|
token_authority,
|
|
|
|
+ token_token_program,
|
|
associated_token_mint,
|
|
associated_token_mint,
|
|
associated_token_authority,
|
|
associated_token_authority,
|
|
|
|
+ associated_token_token_program,
|
|
mint_authority,
|
|
mint_authority,
|
|
mint_freeze_authority,
|
|
mint_freeze_authority,
|
|
mint_decimals,
|
|
mint_decimals,
|
|
|
|
+ mint_token_program,
|
|
bump,
|
|
bump,
|
|
program_seed,
|
|
program_seed,
|
|
realloc,
|
|
realloc,
|
|
@@ -600,20 +627,33 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|
.expect("bump must be provided with seeds"),
|
|
.expect("bump must be provided with seeds"),
|
|
program_seed: into_inner!(program_seed).map(|id| id.program_seed),
|
|
program_seed: into_inner!(program_seed).map(|id| id.program_seed),
|
|
});
|
|
});
|
|
- let associated_token = match (associated_token_mint, associated_token_authority) {
|
|
|
|
- (Some(mint), Some(auth)) => Some(ConstraintAssociatedToken {
|
|
|
|
|
|
+ let associated_token = match (
|
|
|
|
+ associated_token_mint,
|
|
|
|
+ associated_token_authority,
|
|
|
|
+ &associated_token_token_program,
|
|
|
|
+ ) {
|
|
|
|
+ (Some(mint), Some(auth), _) => Some(ConstraintAssociatedToken {
|
|
wallet: auth.into_inner().auth,
|
|
wallet: auth.into_inner().auth,
|
|
mint: mint.into_inner().mint,
|
|
mint: mint.into_inner().mint,
|
|
|
|
+ token_program: associated_token_token_program
|
|
|
|
+ .as_ref()
|
|
|
|
+ .map(|a| a.clone().into_inner().token_program),
|
|
}),
|
|
}),
|
|
- (Some(mint), None) => return Err(ParseError::new(
|
|
|
|
|
|
+ (Some(mint), None, _) => return Err(ParseError::new(
|
|
mint.span(),
|
|
mint.span(),
|
|
"authority must be provided to specify an associated token program derived address",
|
|
"authority must be provided to specify an associated token program derived address",
|
|
)),
|
|
)),
|
|
- (None, Some(auth)) => {
|
|
|
|
|
|
+ (None, Some(auth), _) => {
|
|
return Err(ParseError::new(
|
|
return Err(ParseError::new(
|
|
auth.span(),
|
|
auth.span(),
|
|
"mint must be provided to specify an associated token program derived address",
|
|
"mint must be provided to specify an associated token program derived address",
|
|
))
|
|
))
|
|
|
|
+ },
|
|
|
|
+ (None, None, Some(token_program)) => {
|
|
|
|
+ return Err(ParseError::new(
|
|
|
|
+ token_program.span(),
|
|
|
|
+ "mint and authority must be provided to specify an associated token program derived address",
|
|
|
|
+ ))
|
|
}
|
|
}
|
|
_ => None,
|
|
_ => None,
|
|
};
|
|
};
|
|
@@ -626,18 +666,26 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- let token_account = match (&token_mint, &token_authority) {
|
|
|
|
- (None, None) => None,
|
|
|
|
|
|
+ let token_account = match (&token_mint, &token_authority, &token_token_program) {
|
|
|
|
+ (None, None, None) => None,
|
|
_ => Some(ConstraintTokenAccountGroup {
|
|
_ => Some(ConstraintTokenAccountGroup {
|
|
mint: token_mint.as_ref().map(|a| a.clone().into_inner().mint),
|
|
mint: token_mint.as_ref().map(|a| a.clone().into_inner().mint),
|
|
authority: token_authority
|
|
authority: token_authority
|
|
.as_ref()
|
|
.as_ref()
|
|
.map(|a| a.clone().into_inner().auth),
|
|
.map(|a| a.clone().into_inner().auth),
|
|
|
|
+ token_program: token_token_program
|
|
|
|
+ .as_ref()
|
|
|
|
+ .map(|a| a.clone().into_inner().token_program),
|
|
}),
|
|
}),
|
|
};
|
|
};
|
|
|
|
|
|
- let mint = match (&mint_decimals, &mint_authority, &mint_freeze_authority) {
|
|
|
|
- (None, None, None) => None,
|
|
|
|
|
|
+ let mint = match (
|
|
|
|
+ &mint_decimals,
|
|
|
|
+ &mint_authority,
|
|
|
|
+ &mint_freeze_authority,
|
|
|
|
+ &mint_token_program,
|
|
|
|
+ ) {
|
|
|
|
+ (None, None, None, None) => None,
|
|
_ => Some(ConstraintTokenMintGroup {
|
|
_ => Some(ConstraintTokenMintGroup {
|
|
decimals: mint_decimals
|
|
decimals: mint_decimals
|
|
.as_ref()
|
|
.as_ref()
|
|
@@ -648,6 +696,9 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|
freeze_authority: mint_freeze_authority
|
|
freeze_authority: mint_freeze_authority
|
|
.as_ref()
|
|
.as_ref()
|
|
.map(|a| a.clone().into_inner().mint_freeze_auth),
|
|
.map(|a| a.clone().into_inner().mint_freeze_auth),
|
|
|
|
+ token_program: mint_token_program
|
|
|
|
+ .as_ref()
|
|
|
|
+ .map(|a| a.clone().into_inner().token_program),
|
|
}),
|
|
}),
|
|
};
|
|
};
|
|
|
|
|
|
@@ -667,11 +718,13 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|
"authority must be provided to initialize a token program derived address"
|
|
"authority must be provided to initialize a token program derived address"
|
|
)),
|
|
)),
|
|
},
|
|
},
|
|
|
|
+ token_program: token_token_program.map(|tp| tp.into_inner().token_program),
|
|
}
|
|
}
|
|
} else if let Some(at) = &associated_token {
|
|
} else if let Some(at) = &associated_token {
|
|
InitKind::AssociatedToken {
|
|
InitKind::AssociatedToken {
|
|
mint: at.mint.clone(),
|
|
mint: at.mint.clone(),
|
|
- owner: at.wallet.clone()
|
|
|
|
|
|
+ owner: at.wallet.clone(),
|
|
|
|
+ token_program: associated_token_token_program.map(|tp| tp.into_inner().token_program),
|
|
}
|
|
}
|
|
} else if let Some(d) = &mint_decimals {
|
|
} else if let Some(d) = &mint_decimals {
|
|
InitKind::Mint {
|
|
InitKind::Mint {
|
|
@@ -683,7 +736,8 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|
"authority must be provided to initialize a mint program derived address"
|
|
"authority must be provided to initialize a mint program derived address"
|
|
))
|
|
))
|
|
},
|
|
},
|
|
- freeze_authority: mint_freeze_authority.map(|fa| fa.into_inner().mint_freeze_auth)
|
|
|
|
|
|
+ freeze_authority: mint_freeze_authority.map(|fa| fa.into_inner().mint_freeze_auth),
|
|
|
|
+ token_program: mint_token_program.map(|tp| tp.into_inner().token_program),
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
InitKind::Program {
|
|
InitKind::Program {
|
|
@@ -731,11 +785,16 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|
ConstraintToken::Address(c) => self.add_address(c),
|
|
ConstraintToken::Address(c) => self.add_address(c),
|
|
ConstraintToken::TokenAuthority(c) => self.add_token_authority(c),
|
|
ConstraintToken::TokenAuthority(c) => self.add_token_authority(c),
|
|
ConstraintToken::TokenMint(c) => self.add_token_mint(c),
|
|
ConstraintToken::TokenMint(c) => self.add_token_mint(c),
|
|
|
|
+ ConstraintToken::TokenTokenProgram(c) => self.add_token_token_program(c),
|
|
ConstraintToken::AssociatedTokenAuthority(c) => self.add_associated_token_authority(c),
|
|
ConstraintToken::AssociatedTokenAuthority(c) => self.add_associated_token_authority(c),
|
|
ConstraintToken::AssociatedTokenMint(c) => self.add_associated_token_mint(c),
|
|
ConstraintToken::AssociatedTokenMint(c) => self.add_associated_token_mint(c),
|
|
|
|
+ ConstraintToken::AssociatedTokenTokenProgram(c) => {
|
|
|
|
+ self.add_associated_token_token_program(c)
|
|
|
|
+ }
|
|
ConstraintToken::MintAuthority(c) => self.add_mint_authority(c),
|
|
ConstraintToken::MintAuthority(c) => self.add_mint_authority(c),
|
|
ConstraintToken::MintFreezeAuthority(c) => self.add_mint_freeze_authority(c),
|
|
ConstraintToken::MintFreezeAuthority(c) => self.add_mint_freeze_authority(c),
|
|
ConstraintToken::MintDecimals(c) => self.add_mint_decimals(c),
|
|
ConstraintToken::MintDecimals(c) => self.add_mint_decimals(c),
|
|
|
|
+ ConstraintToken::MintTokenProgram(c) => self.add_mint_token_program(c),
|
|
ConstraintToken::Bump(c) => self.add_bump(c),
|
|
ConstraintToken::Bump(c) => self.add_bump(c),
|
|
ConstraintToken::ProgramSeed(c) => self.add_program_seed(c),
|
|
ConstraintToken::ProgramSeed(c) => self.add_program_seed(c),
|
|
ConstraintToken::Realloc(c) => self.add_realloc(c),
|
|
ConstraintToken::Realloc(c) => self.add_realloc(c),
|
|
@@ -763,6 +822,12 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|
"init must be provided before token authority",
|
|
"init must be provided before token authority",
|
|
));
|
|
));
|
|
}
|
|
}
|
|
|
|
+ if self.token_token_program.is_some() {
|
|
|
|
+ return Err(ParseError::new(
|
|
|
|
+ c.span(),
|
|
|
|
+ "init must be provided before token account token program",
|
|
|
|
+ ));
|
|
|
|
+ }
|
|
if self.mint_authority.is_some() {
|
|
if self.mint_authority.is_some() {
|
|
return Err(ParseError::new(
|
|
return Err(ParseError::new(
|
|
c.span(),
|
|
c.span(),
|
|
@@ -781,6 +846,12 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|
"init must be provided before mint decimals",
|
|
"init must be provided before mint decimals",
|
|
));
|
|
));
|
|
}
|
|
}
|
|
|
|
+ if self.mint_token_program.is_some() {
|
|
|
|
+ return Err(ParseError::new(
|
|
|
|
+ c.span(),
|
|
|
|
+ "init must be provided before mint token program",
|
|
|
|
+ ));
|
|
|
|
+ }
|
|
if self.associated_token_mint.is_some() {
|
|
if self.associated_token_mint.is_some() {
|
|
return Err(ParseError::new(
|
|
return Err(ParseError::new(
|
|
c.span(),
|
|
c.span(),
|
|
@@ -793,6 +864,12 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|
"init must be provided before associated token authority",
|
|
"init must be provided before associated token authority",
|
|
));
|
|
));
|
|
}
|
|
}
|
|
|
|
+ if self.associated_token_token_program.is_some() {
|
|
|
|
+ return Err(ParseError::new(
|
|
|
|
+ c.span(),
|
|
|
|
+ "init must be provided before associated token account token program",
|
|
|
|
+ ));
|
|
|
|
+ }
|
|
self.init.replace(c);
|
|
self.init.replace(c);
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
@@ -988,6 +1065,31 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ fn add_token_token_program(&mut self, c: Context<ConstraintTokenProgram>) -> ParseResult<()> {
|
|
|
|
+ if self.token_token_program.is_some() {
|
|
|
|
+ return Err(ParseError::new(
|
|
|
|
+ c.span(),
|
|
|
|
+ "token token_program already provided",
|
|
|
|
+ ));
|
|
|
|
+ }
|
|
|
|
+ self.token_token_program.replace(c);
|
|
|
|
+ Ok(())
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn add_associated_token_token_program(
|
|
|
|
+ &mut self,
|
|
|
|
+ c: Context<ConstraintTokenProgram>,
|
|
|
|
+ ) -> ParseResult<()> {
|
|
|
|
+ if self.associated_token_token_program.is_some() {
|
|
|
|
+ return Err(ParseError::new(
|
|
|
|
+ c.span(),
|
|
|
|
+ "associated token token_program already provided",
|
|
|
|
+ ));
|
|
|
|
+ }
|
|
|
|
+ self.associated_token_token_program.replace(c);
|
|
|
|
+ Ok(())
|
|
|
|
+ }
|
|
|
|
+
|
|
fn add_mint_authority(&mut self, c: Context<ConstraintMintAuthority>) -> ParseResult<()> {
|
|
fn add_mint_authority(&mut self, c: Context<ConstraintMintAuthority>) -> ParseResult<()> {
|
|
if self.mint_authority.is_some() {
|
|
if self.mint_authority.is_some() {
|
|
return Err(ParseError::new(c.span(), "mint authority already provided"));
|
|
return Err(ParseError::new(c.span(), "mint authority already provided"));
|
|
@@ -1018,6 +1120,17 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
|
|
Ok(())
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ fn add_mint_token_program(&mut self, c: Context<ConstraintTokenProgram>) -> ParseResult<()> {
|
|
|
|
+ if self.mint_token_program.is_some() {
|
|
|
|
+ return Err(ParseError::new(
|
|
|
|
+ c.span(),
|
|
|
|
+ "mint token_program already provided",
|
|
|
|
+ ));
|
|
|
|
+ }
|
|
|
|
+ self.mint_token_program.replace(c);
|
|
|
|
+ Ok(())
|
|
|
|
+ }
|
|
|
|
+
|
|
fn add_mut(&mut self, c: Context<ConstraintMut>) -> ParseResult<()> {
|
|
fn add_mut(&mut self, c: Context<ConstraintMut>) -> ParseResult<()> {
|
|
if self.mutable.is_some() {
|
|
if self.mutable.is_some() {
|
|
return Err(ParseError::new(c.span(), "mut already provided"));
|
|
return Err(ParseError::new(c.span(), "mut already provided"));
|