Parsing a TypeName property using BCS TypeScript

assume I have following data structure on sui smart contract

public struct IntentData has copy, drop, store {
    intent_id: vector,
    user: String,
    expiry: u64,
    deposited_token: TypeName,  // <===
    deposited_amount: u64,
    exact_in: bool,
    slippage_tolerance: u8,
    out_token: TypeName,        // <===
    out_chain_id: String,
    expected_out_amount: u64,
    min_out_amount: u64
}

and I want to create an object of this type in my typescript client and send it over a transaction. RIght now I am using, following code


const IntentDataSchema = bcs.struct("IntentData", {
        intent_id: bcs.vector(bcs.u8()), // vector<u8> 
        user: bcs.string(),              // String is a utf-8 encoded string
        expiry: bcs.u64(),               
        deposited_token: bcs.TypeTag,   //  (e.g., "0x2::sui::SUI")
        deposited_amount: bcs.u64(),
        exact_in: bcs.bool(),
        slippage_tolerance: bcs.u8(),
        out_token: bcs.TypeTag,        
        out_chain_id: bcs.string(),
        expected_out_amount: bcs.u64(),
        min_out_amount: bcs.u64(),
    });

    // 2. Prepare the data to be serialized.
    const dataToSerialize = {
        intent_id: new Uint8Array(ethers.toBeArray(intentData.intentId)), 
        user: intentData.receiverAddress,
        expiry: BigInt(1770909953), // Example timestamp
        deposited_token: TypeTagSerializer.parseFromStr("0x2::sui::SUI"), // Example TypeName string
        deposited_amount: BigInt(intentData.inputAmount),
        exact_in: true,
        slippage_tolerance: 100,
        out_token: TypeTagSerializer.parseFromStr("0x2::sui::SUI"),
        out_chain_id: "80003",
        expected_out_amount: BigInt(intentData.outputAmount),
        min_out_amount: BigInt(intentData.minOutputAmount),
    };

    // 3. Serialize the data.
    const serializedBytes = IntentDataSchema.serialize(dataToSerialize).toBytes();


    const tx = new Transaction()
    const target = process.env.SUI_ESCROW_ADDRESS + "::intent_escrow::create_intent";
    tx.moveCall({
        target,
        arguments: [
            tx.object(process.env.SUI_ESCROW_RELAYER as string),
            tx.object(process.env.SUI_ESCROW as string),
            tx.pure(serializedBytes)
        ]
    })

  1. My questing is, Am I parsing the “TypeName” properly? As I am keep getting error on transaction failure saying “InvalidUsageOfPureArg”. Notice two of my IntentData struct have TypeName, i.e, “deposit_token”, “out_token”
  2. here is the digest of one of failed tx Gi5Sxet7HB1W52SW3D7j9grNuWKdcN2W3i611BCGP2mE

To create an intent like this, you’d need to pass in the fields as individual arguments. You cannot construct this manually on the client side.

Using generic type arguments in your struct might be useful as well:

public struct IntentData<InToken, OutToken> has copy, drop, store {
    intent_id: vector<u8>,
    user: String,
    expiry: u64,
    deposited_amount: u64,
    exact_in: bool,
    slippage_tolerance: u8,
    out_chain_id: String,
    expected_out_amount: u64,
    min_out_amount: u64
}

then the transaction on the client side would look something like:

  const tx = new Transaction()
  const target = process.env.SUI_ESCROW_ADDRESS + "::intent_escrow::create_intent";
  tx.moveCall({
      target,
      typeArguments: [
          "0x2::sui::SUI", 
          "0x2::sui::SUI"
      ],
      arguments: [
          tx.object(process.env.SUI_ESCROW_RELAYER as string),
          tx.object(process.env.SUI_ESCROW as string),
          ...each intent field as individual arguments
      ]
  })

Does that help?