https://github.com/Cajarty/Seed
As per the "Module, Smart Contracts & The SVM" design article, this contribution includes the implementation for Smart Contracts (Modules), the Seed Virtual Machine (SVM), and the virtualized ledger, as well as a basic module unit testing framework and a basic Seed module cryptocurrency implementation.
The relevant pull request can be found here.
The base Module class can be found in the module.js file, with seed.js being a solid example implementation showcasing how to use it.
Modules contain local state data, state data for each user, a name, and invokable functions. These functions can be either state-modifying functions or getter functions.
To create a module, a developer would require the module.js file and invoke the export function. They would pass the require information for creation into the constructor under the "info" parameter. Below is a simple example of creating a module, who's state is one variable anyone can increment.
let module = require("./seedSrc/module.js").createModule({
module : "ExampleModule",
initialData : {
stateVariable : 0
}
functions : {
incrementCounter : function(container, changeContext) {
changeContext.add(1, { key : "stateVariable" });
return changeContext;
},
getCounters : function(container) {
return container.getModuleData("stateVariable");
}
}
});
This module has one local variable, "stateVariable", which is incremented any time any user invokes the "incrementCounter" function. "getCounters" is a getter function which returns the variable.
The SVM is a pseudo-VirtualMachine used to manage the modules and leger. The SVM can be found in the virtualMachine.js file.
To add a module to the virtualMachine, you simple require the file, call them "getVirtualMachine" exported function, and then call the "addModule" function.
The Container class is the "read-only" connection between a modules function and the world state. This container is the first parameter in any state-modifying or getter functions added to a module. The container allows users to read any modules data (even other modules), any user's data (for any module), as well as get deterministic pseudo-random integer/floats, access any modules getter functions, and even access a local-modules state-modifying function (passing it a changeContext, which it will modify and return back the results).
The ChangeContext class is the "write-only" connection between a modules function and the world state. Any function which intends on modifying the world state (therefore, non-getter functions) requires a ChangeContext parameter as the second parameter.
The ChangeContext has functions that wrap modifying the world state, such as "add"/"subtract" and "set" methods.
The Ledger is a virtualized ledger class that mimics what the state of the world currently is for the SVM. The ledger can have a ChangeContext applied to it, which modifies the current state by whatever the ChangeContext intends on changing. The only real logic in it is the "applyChanges" function, which takes a ChangeContext object and modifies its state by the values in the ChangeContext.
The Seed module is an ERC-20 implementation of a cryptocurrency ported over to the Seed ecosystem. This standard was copied due to its proven logic and being easily testable.
This interface includes methods for transfering SEED, giving allowances, transfering on other users behalfs, getting the symbol/total supply/decimals,etc. The full ERC-20 compliant standard.
A full testing scenario with the Seed module can be found in the scenarioTest.js file.
The ModuleTester is a class to help with scenario testing/unit testing modules. It's a simple class which just helps with simulating functions being invoked, modifying the ledger accordingly, and asserting what the values should be. The scenarioTest.js file runs through scenarios which utilize the tester.
https://github.com/CarsonRoscoe