Yes, you're correct. When creating an output for a transaction, by default you only need to provide the datum hash. The consumer of that output is by default required to provide the datum that matches that hash.
If you want to provide the datum nonetheless for an output that you're creating in order to do assertions on it inside your spending validator you can do so like this:
const scripts = PlutusScripts.new();
scripts.add(PlutusScript.from_bytes(Buffer.from(<your script contract cborHex>, 'hex')));
const datumFields = CSL.PlutusList.new();
datumFields.add(CSL.PlutusData.new_integer(CSL.BigInt.from_str( ... )));
const datumConstr = CSL.ConstrPlutusData.new(
CSL.BigNum.from_str('0'),
datumFields
);
const datum = CSL.PlutusData.new_constr_plutus_data(datumConstr);
const transactionWitnessSet = CSL.TransactionWitnessSet.new();
transactionWitnessSet.set_plutus_scripts(scripts);
transactionWitnessSet.set_plutus_data(datum);
transactionWitnessSet.set_redeemers(...);
txBody.set_script_data_hash(hash_script_data(..., getCostModels(), datum));
{...}
export const COST_MODEL = [197209, 0, 1, 1, 396231, 621, 0, 1, 150000, 1000, 0, 1, 150000, 32, 2477736, 29175, 4, 29773, 100, 29773, 100, 29773, 100, 29773, 100, 29773, 100, 29773, 100, 100, 100, 29773, 100, 150000, 32, 150000, 32, 150000, 32, 150000, 1000, 0, 1, 150000, 32, 150000, 1000, 0, 8, 148000, 425507, 118, 0, 1, 1, 150000, 1000, 0, 8, 150000, 112536, 247, 1, 150000, 10000, 1, 136542, 1326, 1, 1000, 150000, 1000, 1, 150000, 32, 150000, 32, 150000, 32, 1, 1, 150000, 1, 150000, 4, 103599, 248, 1, 103599, 248, 1, 145276, 1366, 1, 179690, 497, 1, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 148000, 425507, 118, 0, 1, 1, 61516, 11218, 0, 1, 150000, 32, 148000, 425507, 118, 0, 1, 1, 148000, 425507, 118, 0, 1, 1, 2477736, 29175, 4, 0, 82363, 4, 150000, 5000, 0, 1, 150000, 32, 197209, 0, 1, 1, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 3345831, 1, 1];
export const getCostModel = () => {
const costModel = CostModel.new();
COST_MODEL.forEach((x, i) => costModel.set(i, Int.new_i32(x)));
const costModels = Costmdls.new();
costModels.insert(Language.new_plutus_v1(), costModel);
return costModels;
}
For more examples I recommend the following resources:
DApp Connector Examples
SpaceBudz Datum Creation