1. Perishable Goods Network
Example business network that shows growers, shippers and importers defining contracts for the price of perishable goods, based on temperature readings received for shipping containers.
Participants Grower Importer Shipper
Assets Contract Shipment
Transactions TemperatureReading ShipmentReceived SetupDemo
2. 模型
1 | /** |
3. 模板构建
建立SetupDemo交易:
This transaction populates the Participant Registries with a Grower, an Importer and a Shipper. The Asset Registries will have a Contract asset and a Shipment asset.
1 | { |
建立TemperatureReading交易:
If the temperature reading falls outside the min/max range of the contract, the price received by the grower will be reduced. You may submit several readings if you wish. Each reading will be aggregated within SHIP_001 Shipment Asset Registry.
1 | { |
建立ShipmentReceived交易:
Submit a ShipmentReceived transaction for SHIP_001 to trigger the payout to the grower, based on the parameters of the CON_001 contract.
If the date-time of the ShipmentReceived transaction is after the arrivalDateTime on CON_001 then the grower will no receive any payment for the shipment.
1 | { |
4. perishable.js
1 | ; |
receive base price1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44it('should receive base price for a shipment within temperature range', () => {
// submit the temperature reading
const tempReading = factory.newTransaction(namespace, 'TemperatureReading');
tempReading.shipment = factory.newRelationship(namespace, 'Shipment', 'SHIP_001');
tempReading.centigrade = 4.5;
return businessNetworkConnection.submitTransaction(tempReading)
.then(() => {
// submit the shipment received
const received = factory.newTransaction(namespace, 'ShipmentReceived');
received.shipment = factory.newRelationship(namespace, 'Shipment', 'SHIP_001');
return businessNetworkConnection.submitTransaction(received);
})
.then(() => {
return businessNetworkConnection.getParticipantRegistry(namespace + '.Grower');
})
.then((growerRegistry) => {
// check the grower's balance
return growerRegistry.get(grower_id);
})
.then((newGrower) => {
// console.log(JSON.stringify(businessNetworkConnection.getBusinessNetwork().getSerializer().toJSON(newGrower)));
newGrower.accountBalance.should.equal(2500);
})
.then(() => {
return businessNetworkConnection.getParticipantRegistry(namespace + '.Importer');
})
.then((importerRegistry) => {
// check the importer's balance
return importerRegistry.get(importer_id);
})
.then((newImporter) => {
newImporter.accountBalance.should.equal(-2500);
})
.then(() => {
return businessNetworkConnection.getAssetRegistry(namespace + '.Shipment');
})
.then((shipmentRegistry) => {
// check the state of the shipment
return shipmentRegistry.get('SHIP_001');
})
.then((shipment) => {
shipment.status.should.equal('ARRIVED');
});
});
receive nothing1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36it('should receive nothing for a late shipment', () => {
// submit the temperature reading
const tempReading = factory.newTransaction(namespace, 'TemperatureReading');
tempReading.shipment = factory.newRelationship(namespace, 'Shipment', 'SHIP_001');
tempReading.centigrade = 4.5;
// advance the javascript clock to create a time-advanced test timestamp
clock.tick(1000000000000000);
return businessNetworkConnection.submitTransaction(tempReading)
.then(() => {
// submit the shipment received
const received = factory.newTransaction(namespace, 'ShipmentReceived');
received.shipment = factory.newRelationship(namespace, 'Shipment', 'SHIP_001');
return businessNetworkConnection.submitTransaction(received);
})
.then(() => {
return businessNetworkConnection.getParticipantRegistry(namespace + '.Grower');
})
.then((growerRegistry) => {
// check the grower's balance
return growerRegistry.get(grower_id);
})
.then((newGrower) => {
// console.log(JSON.stringify(businessNetworkConnection.getBusinessNetwork().getSerializer().toJSON(newGrower)));
newGrower.accountBalance.should.equal(2500);
})
.then(() => {
return businessNetworkConnection.getParticipantRegistry(namespace + '.Importer');
})
.then((importerRegistry) => {
// check the importer's balance
return importerRegistry.get(importer_id);
})
.then((newImporter) => {
newImporter.accountBalance.should.equal(-2500);
});
});
apply penalty for min temperature violation1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34it('should apply penalty for min temperature violation', () => {
// submit the temperature reading
const tempReading = factory.newTransaction(namespace, 'TemperatureReading');
tempReading.shipment = factory.newRelationship(namespace, 'Shipment', 'SHIP_001');
tempReading.centigrade = 1;
return businessNetworkConnection.submitTransaction(tempReading)
.then(() => {
// submit the shipment received
const received = factory.newTransaction(namespace, 'ShipmentReceived');
received.shipment = factory.newRelationship(namespace, 'Shipment', 'SHIP_001');
return businessNetworkConnection.submitTransaction(received);
})
.then(() => {
return businessNetworkConnection.getParticipantRegistry(namespace + '.Grower');
})
.then((growerRegistry) => {
// check the grower's balance
return growerRegistry.get(grower_id);
})
.then((newGrower) => {
// console.log(JSON.stringify(businessNetworkConnection.getBusinessNetwork().getSerializer().toJSON(newGrower)));
newGrower.accountBalance.should.equal(4000);
})
.then(() => {
return businessNetworkConnection.getParticipantRegistry(namespace + '.Importer');
})
.then((importerRegistry) => {
// check the importer's balance
return importerRegistry.get(importer_id);
})
.then((newImporter) => {
newImporter.accountBalance.should.equal(-4000);
});
});
apply penalty for max temperature violation1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34it('should apply penalty for max temperature violation', () => {
// submit the temperature reading
const tempReading = factory.newTransaction(namespace, 'TemperatureReading');
tempReading.shipment = factory.newRelationship(namespace, 'Shipment', 'SHIP_001');
tempReading.centigrade = 11;
return businessNetworkConnection.submitTransaction(tempReading)
.then(() => {
// submit the shipment received
const received = factory.newTransaction(namespace, 'ShipmentReceived');
received.shipment = factory.newRelationship(namespace, 'Shipment', 'SHIP_001');
return businessNetworkConnection.submitTransaction(received);
})
.then(() => {
return businessNetworkConnection.getParticipantRegistry(namespace + '.Grower');
})
.then((growerRegistry) => {
// check the grower's balance
return growerRegistry.get(grower_id);
})
.then((newGrower) => {
// console.log(JSON.stringify(businessNetworkConnection.getBusinessNetwork().getSerializer().toJSON(newGrower)));
newGrower.accountBalance.should.equal(5000);
})
.then(() => {
return businessNetworkConnection.getParticipantRegistry(namespace + '.Importer');
})
.then((importerRegistry) => {
// check the importer's balance
return importerRegistry.get(importer_id);
})
.then((newImporter) => {
newImporter.accountBalance.should.equal(-5000);
});
});