Search code examples
solanaanchor-solana

What's the best way to pass arbitrary length data to an Anchor (Solana) instruction call?


I'd like to store an arbitrary length structured data collection in a Solana account... Something like what [{foo: "bar"}, {foo: "quux"}] would be in JS, ideally with arbitrary nesting in the objects. I'm thinking to store this in a Vec<T> within the Rust structs (is this the right approach?) but it's quite unclear how to send this over the wire with Anchor RPC, i.e., how to borsh encode it.

To be more specific, for instance I have this instruction but I don't know how to send data over to it using Anchor's program.rpc.createWorkSpec.

Any pointers?


Solution

  • OK so this ended up working pretty much how I expected to start, so I must have been doing something wrong in the intermediate things I've tried.

    You can see https://github.com/workbenchapp/worknet/blob/c51113b09b64201cc25a22dfb845a295f6ee5072/programs/worknet/src/lib.rs#L12 which accepts a Vec<Container> as one of its args ...

    #[derive(Default, Copy, Clone, AnchorSerialize, AnchorDeserialize)]
    pub struct PortMapping {
        pub inner_port: u16,
        pub outer_port: u16,
        pub port_type: PortType,
    }
    
    #[derive(Clone, AnchorSerialize, AnchorDeserialize)]
    pub struct Container {
        pub image: String,
        pub args: Vec<String>,
        pub port_mappings: Vec<PortMapping>,
    }
    
    #[account]
    #[derive(Default)]
    pub struct WorkSpec {
        containers: Vec<Container>,
    }
    

    Can be passed a nested object/array mapping (with rust_snake translated to jsCamelCase)

    const specContainers = [
        {
            image: "alpine",
            args: ["echo", "hi"],
            portMappings: [],
        },
    ];
    await program.rpc.createWorkSpec(specContainers, {
        accounts: {
            spec: spec.publicKey,
            authority: provider.wallet.publicKey,
            systemProgram: SystemProgram.programId,
        },
        signers: [spec],
    });