问题
I have a network set up that is based on the fabcar example. Customized the chaincode and the folder structure, and it all seems to compile and fire up just fine. But now, I am trying to find out whether I can use function Contract.submitTransaction()
(found in invoke.ts and covered in the docs) or a more applicable function to pass somewhat more complex arguments for custom type Shipment
which is based on type Car of the original example. In the example, Car
is simply a flat type of string
s, which you can simply pass to Contract.submitTransaction()
, which takes only string arguments, like so:
await contract.submitTransaction('createCar', 'CAR12', 'Honda', 'Accord', 'Black', 'Tom');
With a type Shipment
composed of multiple "sub-types", that gets a little harder:
import { TransitStatusEnum } from "../enum/transitstatusenum";
import { FreightContainer } from "./freightcontainer";
import { Company } from "./company";
export class Shipment {
public docType?: string;
public id: string;
public status: TransitStatusEnum;
public containers: FreightContainer[];
public shipper?: Company;
private totalShipmentValue?: number = 0;
constructor() {
if (!this.containers) {
console.log("Shipment does not (yet) contain any containers, shipmentValue is 0");
return;
}
for (let container of this.containers) {
this.totalShipmentValue += container.transitAgreement.cargoValue;
}
}
}
Below you'll find the function that Contract.submitTransaction()
should invoke instead of CreateCar()
:
public async createShipment(ctx: Context, id: string, status: TransitStatusEnum, shipper: Company, containers?: FreightContainer[]) {
console.info('============= START : Create Shipment ===========');
const shipment: Shipment = {
docType: 'shipment',
id,
status,
containers,
shipper
};
await ctx.stub.putState(id, Buffer.from(JSON.stringify(shipment)));
console.info('============= END : Create Shipment ===========');
}
I could make factories for these self-defined types and have the types generated based on string
values instead of types passed to createShipment()
, or pass a stringified object (of objects/arrays, of more objects/arrays). But I'd like to know if (especially the latter, which gives me chills) is truly necessary. The docs only mention this Contract.submitTransaction()
function as a way to submit a transaction to the blockchain.
Should I go with my factory solution? Is there another function that I can use to be able to submit transactions using types? Or is this not the way I should structure my chaincode and should I consider simplifying it completely?
回答1:
An object is different for each language that Hyperledger Fabric supports. For example, there are SDKs available for JavaScript (Node.js), Java, Go and Python. Furthermore the chaincode itself could be written in either JavaScript, Java or Go.
To stay language neutral, the internal representation of the arguments is just an array of bytes, which is defined in the protobuf specification which Fabric uses for internal communication. Fabric SDKs also tend to toss in a conversion to a string definition. Your only option is to work with bytes or strings. You could use your own custom parsing or for more advanced use, you could use some type of serialization protocol (see comparison). However, both your application and chaincode needs to support it.
When you need to send objects, I would recommend creating a chaincode function such as createShipment
for your case, which accepts as many arguments as needed to construct the object. If the object itself contains an array of objects (FreightContainer
) you could register this as an object itself (createFreightContainer
) which contains an ID to the Shipment
.
来源:https://stackoverflow.com/questions/59359370/can-i-pass-objects-to-a-hyperledger-fabric-transaction