metaplex-foundation/solita

fixable type not bubbling properly

CalebEverett opened this issue · 10 comments

I have an account struct with a custom enum type as one of its properties:

#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug, PartialEq, Eq)]
pub enum MarketState {
    Uninitialized,
    Created,
    Suspended,
    Active,
    Ended,
}

#[account]
#[derive(PartialEq, Debug, Eq)]
pub struct PrimaryMarketParameters {
    pub mint: Pubkey,
    pub platform: Pubkey,
    pub platform_fee_percentage: u64, // IN BASIS POINTS (10_000)
    pub edition_price: u64,
    pub max_supply: u64,
    pub market_state: MarketState,
}

The MarketState type is generated as:

import * as beet from '@metaplex-foundation/beet'
/**
 * @category enums
 * @category generated
 */
export enum MarketState {
  Uninitialized,
  Created,
  Suspended,
  Active,
  Ended,
}

/**
 * @category userTypes
 * @category generated
 */
export const marketStateBeet = beet.fixedScalarEnum(
  MarketState
) as beet.FixedSizeBeet<MarketState, MarketState>

But primaryMarketParametersBeet is being rendered as a BeetStruct instead of a FixableBeetStruct

export const primaryMarketParametersBeet = new beet.BeetStruct<
  PrimaryMarketParameters,
  PrimaryMarketParametersArgs & {
    accountDiscriminator: number[] /* size: 8 */
  }
>(
  [
    ['accountDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)],
    ['mint', beetSolana.publicKey],
    ['platform', beetSolana.publicKey],
    ['platformFeePercentage', beet.u64],
    ['editionPrice', beet.u64],
    ['maxSupply', beet.u64],
    ['marketState', marketStateBeet],
  ],
  PrimaryMarketParameters.fromArgs,
  'PrimaryMarketParameters'
)

and marketStateBeet is throwing this error:

Type 'FixedSizeBeet<MarketState, MarketState>' is not assignable to type 'FixedSizeBeet<any, Partial<any>>'.
  Type 'ScalarFixedSizeBeet<MarketState, MarketState>' is not assignable to type 'FixedSizeBeet<any, Partial<any>>'.
    Type 'ScalarFixedSizeBeet<MarketState, MarketState>' is not assignable to type 'ElementCollectionFixedSizeBeet<any, Partial<any>>'.
      Type 'ScalarFixedSizeBeet<MarketState, MarketState>' is not assignable to type 'BeetReadWrite<any, Partial<any>>'.
        Types of property 'write' are incompatible.
          Type '(buf: Buffer, offset: number, value: MarketState) => void' is not assignable to type '(buf: Buffer, offset: number, value: Partial<any>) => void'.
            Types of parameters 'value' and 'value' are incompatible.
              Type 'Partial<any>' is not assignable to type 'MarketState'.ts(2322)

I can resolve that error by editing the generated code so that primaryMarketParametersBeet is a FixableBeetStruct.

If I make one of the fields in PrimaryMarketParameters an Option, it generates as FixableBeetStruct

https://github.com/CalebEverett/solita/blob/d2660c849e5ea52d88cdf0b2f2ab9b77c0c1287a/test/anchor-examples/basic-4/programs/basic-4/src/lib.rs#L66

If you run yarn test:anchor:basic4 it will produce the error above.

Is the fix here to make structs that have enum fields Fixable or to change the assignment to Partial?

Not sure if this is a hack, but allowing V to also be of type T in beet.FixedSizeBeet avoids the error:

FixedSizeBeet<T, V = Partial<T> | T>`

Thanks for reporting this .. are you using the latest solita version?
I did attempt to fix just that before and it worked for the cases I knew of.

I'll have a look and try to address it.

Thanks. I was using the latest version - happy to try to track it down, if you could give me a couple points on approach - things to investigate. I wasn't totally sure what was going on. I had field on a struct that was a scalar enum, that seemed like it's size wasn't dependent on any other data, so a FixedBeet should have been fine, but it errored unless the struct was Fixable.

I just ran yarn test:anchor:basic4 on latest master and the tests pass for me and the generated TypeScript for that example checks out.
Maybe you could link me to a small repro of the problem you're facing when you use this with your program?

Hi, I put a small example here on the basic4 example adding an enum field to the Counter struct that produces the error for me.

https://github.com/CalebEverett/solita/blob/d2660c849e5ea52d88cdf0b2f2ab9b77c0c1287a/test/anchor-examples/basic-4/programs/basic-4/src/lib.rs#L66

src/generated/accounts/Counter.ts:152:16 - error TS2322: Type 'FixedSizeBeet<Status, Status>' is not assignable to type 'FixedSizeBeet<any, Partial<any>>'.
  Type 'ScalarFixedSizeBeet<Status, Status>' is not assignable to type 'FixedSizeBeet<any, Partial<any>>'.
    Type 'ScalarFixedSizeBeet<Status, Status>' is not assignable to type 'ElementCollectionFixedSizeBeet<any, Partial<any>>'.
      Type 'ScalarFixedSizeBeet<Status, Status>' is not assignable to type 'BeetReadWrite<any, Partial<any>>'.
        Types of property 'write' are incompatible.
          Type '(buf: Buffer, offset: number, value: Status) => void' is not assignable to type '(buf: Buffer, offset: number, value: Partial<any>) => void'.
            Types of parameters 'value' and 'value' are incompatible.
              Type 'Partial<any>' is not assignable to type 'Status'.

152     ['status', statusBeet],

Thanks will have a look.

Hey I'm sorry, but I cannot reproduce the issue.
Copied your lib.rs and ran solita on it, but it produces code that builds fine.
Screen Shot 2022-04-27 at 8 35 22 AM

Maybe you could push an example all setup to produce the issue and also check in the IDL + generated code please so I can see what problem you are seeing?

I just applied a bunch of changes to guarantee better types (also updated beet for that).

Published as v0.5.4. Could you please see if this fixes your problem or otherwise provide a repro on github?

Make sure to upgrade to latest beet as well (v0.1.4)

Ok, I had just updated to 0.5.3 and was still getting the issue, but let me update for latest master again.

that did the trick - thank you