diff --git a/.gitignore b/.gitignore index 0a7780f6..4af7dbdc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,20 @@ bundles/* discify/* dist/* +docs/_build/* +docs/blockchain/account-store.rst +docs/blockchain/event-hub.rst +docs/blockchain/executor.rst +docs/blockchain/name-resolver.rst +docs/blockchain/signer.rst +docs/common/logger.rst +docs/common/validator.rst +docs/contracts/contract-loader.rst +docs/dfs/dfs-interface.rst +docs/dfs/ipfs.rst +docs/encryption/cryptor-unencrypted.rst node_modules/* .env.local ipfs-contractus -package-lock.json.* package-lock.json -docs/_build/* +package-lock.json.* diff --git a/.npmignore b/.npmignore index 0b45f10e..7b27b94d 100644 --- a/.npmignore +++ b/.npmignore @@ -1,9 +1,10 @@ -.env bundles/bcc/bcc.js.map bundles/bcc/dbcpPath.json discify/ +docs/* docu/ scripts/ src/ +.env tsconfig.json -tslint.json \ No newline at end of file +tslint.json diff --git a/README.md b/README.md index 64a9fcf2..9ed91f57 100644 --- a/README.md +++ b/README.md @@ -272,7 +272,7 @@ const definition: Envelope = { "name": "Data Contract Sample", "description": "reiterance oxynitrate sat alternize acurative", "version": "0.1.0", - "author": "contractus", + "author": "evan GmbH", "dataSchema": { "list_settable_by_member": { "$id": "list_settable_by_member_schema", diff --git a/VERSIONS.md b/VERSIONS.md index b9843443..8491ef01 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -5,6 +5,23 @@ ### Fixes ### Deprecations + +## Version 1.1.0 +### Features +- add support for wallet/proxy contracts (current implementation allows n wallet owner with a required confirmation count of 1, to allow grouping of accounts) +- add `ExecutorWallet`, that wraps calls to `Wallet`, but behaves like the normal `Executor` +- add `ExecutorAgent`, that wraps contract creation and interaction to edge-server actions +- add `Claims` module for issuing and managing claims about other parties +- add `getCallOwner` to get a `ServiceContracts`s call creator + +### Fixes +- add validation for service definitions, calls and answers to `ServiceContract` +- remove `@evan.network/smart-contracts-admin` dependency + +### Deprecations +- remove endpoint property from service contracts + + ## Version 1.0.2 ### Features - add support for adding sharing file hashes to cache to avoid duplicate contract calls diff --git a/docs/Makefile b/docs/Makefile index a9fb0f68..dd0fb1c3 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -8,6 +8,8 @@ SPHINXPROJ = blockchain-core SOURCEDIR = . BUILDDIR = _build +dbcpDocsUrl = "https://raw.githubusercontent.com/evannetwork/dbcp/develop/docs/" + # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) @@ -17,4 +19,17 @@ help: # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile + # retrieve required docu files from dbcp + wget -P blockchain -N "$(dbcpDocsUrl)blockchain/account-store.rst" + wget -P blockchain -N "$(dbcpDocsUrl)blockchain/event-hub.rst" + wget -P blockchain -N "$(dbcpDocsUrl)blockchain/executor.rst" + wget -P blockchain -N "$(dbcpDocsUrl)blockchain/name-resolver.rst" + wget -P blockchain -N "$(dbcpDocsUrl)blockchain/signer.rst" + wget -P common -N "$(dbcpDocsUrl)common/logger.rst" + wget -P common -N "$(dbcpDocsUrl)common/validator.rst" + wget -P contracts -N "$(dbcpDocsUrl)contracts/contract-loader.rst" + wget -P dfs -N "$(dbcpDocsUrl)dfs/dfs-interface.rst" + wget -P dfs -N "$(dbcpDocsUrl)dfs/ipfs.rst" + wget -P encryption -N "$(dbcpDocsUrl)encryption/cryptor-unencrypted.rst" + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/_static/agent_tx_transparent.png b/docs/_static/agent_tx_transparent.png new file mode 100644 index 00000000..3c4baaeb Binary files /dev/null and b/docs/_static/agent_tx_transparent.png differ diff --git a/docs/_static/wallet_tx_transparent.png b/docs/_static/wallet_tx_transparent.png new file mode 100644 index 00000000..644a9a9b Binary files /dev/null and b/docs/_static/wallet_tx_transparent.png differ diff --git a/docs/blockchain/account-store.rst b/docs/blockchain/account-store.rst deleted file mode 100644 index 5978991b..00000000 --- a/docs/blockchain/account-store.rst +++ /dev/null @@ -1,109 +0,0 @@ -================================================================================ -Account Store -================================================================================ - -.. list-table:: - :widths: auto - :stub-columns: 1 - - * - Class Name - - AccountStore - * - Implements - - `KeyStoreInterface `__ - * - Extends - - `Logger `_ - * - Source - - `account-store.ts `__ - -The `AccountStore `_ implements the `KeyStoreInterface `_ and is a wrapper for a storage, where evan.network account ids are stored. The default `AccountStore `_ takes an account --> private key mapping as a pojo as its arguments and uses this to perform lookups, when the :ref:`getPrivateKey ` function is called. This lookup needs to be done, when transactions are signed by the `InternalSigner `_ (see `Signer `_). - -Note that the return value of the :ref:`getPrivateKey ` function is a promise. This may not be required in the default `AccountStore `_, but this allows you to implement own implementations of the `KeyStoreInterface `_, which may enforce a more strict security behavior or are able to access other sources for private keys. - - - ------------------------------------------------------------------------------- - -.. _accountstore_constructor: - -constructor -================================================================================ - -.. code-block:: typescript - - new AccountStore(options); - -Creates a new AccountStore instance. - ----------- -Parameters ----------- - -#. ``options`` - ``AccountStoreOptions``: options for AccountStore constructor. - * ``accounts`` - ``any``: object with accountid/privatekey mapping - * ``log`` - ``Function`` (optional): function to use for logging: ``(message, level) => {...}`` - * ``logLevel`` - |source logLevel|_ (optional): messages with this level will be logged with ``log`` - * ``logLog`` - |source logLogInterface|_ (optional): container for collecting log messages - * ``logLogLevel`` - |source logLevel|_ (optional): messages with this level will be pushed to ``logLog`` - -------- -Returns -------- - -``AccountStore`` instance - -------- -Example -------- - -.. code-block:: typescript - - const accountStore = new AccountStore({ - accounts: { - '0x1234': '12479abc3df' - } - }); - - - --------------------------------------------------------------------------------- - -.. _accountstore_getPrivateKey: - -getPrivateKey -=================== - -.. code-block:: javascript - - accountStore.getPrivateKey(accountId); - -get private key for given account - - - ----------- -Parameters ----------- - -#. ``accountId`` - ``string``: eth accountId - -------- -Returns -------- - -Promise resolves to ``string``: private key for this account - -------- -Example -------- - -.. code-block:: javascript - - const privateKey = await runtime.accountStore.getPrivateKey('0x0000000000000000000000000000000000000002'); - -.. required for building markup - -.. |source logLevel| replace:: ``LogLevel`` -.. _source logLevel: /common/logger.html#loglevel - -.. |source logLogInterface| replace:: ``LogLogInterface`` -.. _source logLogInterface: /common/logger.html#logloginterface diff --git a/docs/blockchain/description.rst b/docs/blockchain/description.rst index 014483fe..3fda0772 100644 --- a/docs/blockchain/description.rst +++ b/docs/blockchain/description.rst @@ -12,7 +12,7 @@ Description - `Description `_ * - Source - `description.ts `_ - * - Tests + * - Examples - `description.spec.ts `_ The Description module is the main entry point for interacting with contract descriptions. It allows you to: diff --git a/docs/blockchain/event-hub.rst b/docs/blockchain/event-hub.rst deleted file mode 100644 index c2c6c1e0..00000000 --- a/docs/blockchain/event-hub.rst +++ /dev/null @@ -1,222 +0,0 @@ -================================================================================ -Event Hub -================================================================================ - -.. list-table:: - :widths: auto - :stub-columns: 1 - - * - Class Name - - EventHub - * - Extends - - `Logger `_ - * - Source - - `event-hub.ts `_ - -The `EventHub `_ helper is wrapper for using contract events. These include -- contract events (e.g. contract factory may trigger an event, announcing the address of the new contract) -- global events (some contracts in the `evan.network `_ economy, like the `MailBox` use such global events) - ------------------------------------------------------------------------------- - -.. _eventhub_constructor: - -constructor -================================================================================ - -.. code-block:: typescript - - new EventHub(options); - -Creates a new EventHub instance. - ----------- -Parameters ----------- - -#. ``options`` - ``EventHubOptions``: options for EventHub constructor. - * ``config`` - ``any``: configuration object for the eventhub module - * ``nameResolver`` - |source nameResolver|_: |source nameResolver|_ instance - * ``contractLoader`` - |source contractLoader|_: |source contractLoader|_ instance - * ``eventWeb3`` - |source web3|_ (optional): |source web3|_ instance used for event handling (metamask web3 can't handle events correct) - * ``log`` - ``Function`` (optional): function to use for logging: ``(message, level) => {...}`` - * ``logLevel`` - |source logLevel|_ (optional): messages with this level will be logged with ``log`` - * ``logLog`` - |source logLogInterface|_ (optional): container for collecting log messages - * ``logLogLevel`` - |source logLevel|_ (optional): messages with this level will be pushed to ``logLog`` - -------- -Returns -------- - -``EventHub`` instance - -------- -Example -------- - -.. code-block:: typescript - - const eventHub = new EventHub({ - config, - nameResolver, - contractLoader, - }); - - - --------------------------------------------------------------------------------- - -.. _eventhub_subscribe: - -subscribe -=================== - -.. code-block:: javascript - - eventHub.subscribe(contractName, contractAddress, eventName, filterFunction, onEvent, fromBlock); - -subscribe to a contract event or a global EventHub event - ----------- -Parameters ----------- - -#. ``contractName`` - ``string``: target contract name (must be available within |source contractLoader|_ ) -#. ``contractAddress`` - ``string``: target contract address -#. ``eventName`` - ``string``: name of the event to subscribe to -#. ``filterFunction`` - ``function``: a function that returns true or a Promise that resolves to true if onEvent function should be applied -#. ``onEvent`` - ``function``: executed when event was fired and the filter matches, gets the event as its parameter -#. ``fromBlock`` - ``string`` (optional): get all events from this block, defaults to ``latest`` - -------- -Returns -------- - -``Promise`` resolves to ``string``: event subscription. - -------- -Example -------- - -.. code-block:: javascript - - // subscribe to the 'ContractEvent' at the EventHub located at '00000000000000000000000000000000deadbeef' - runtime.eventHub - .subscribe( - 'EventHub', - '00000000000000000000000000000000deadbeef', - 'ContractEvent', - (event) => true, - (event) => { - console.dir(event) - } - ) - .then((result) => { subscription = result; }) - ------------------------------------------------------------------------------- - - -.. _eventhub_once: - -once -=================== - -.. code-block:: javascript - - eventHub.once(contractName, contractAddress, eventName, filterFunction, onEvent, fromBlock); - -subscribe to a contract event or a global EventHub event, remove subscription when filterFunction matched - ----------- -Parameters ----------- - -#. ``toRemove`` - ``any``: -#. ``contractAddress`` - ``string``: target contract address -#. ``eventName`` - ``string``: name of the event to subscribe to -#. ``filterFunction`` - ``function``: a function that returns true or a Promise that resolves to true if onEvent function should be applied -#. ``onEvent`` - ``function``: executed when event was fired and the filter matches, gets the event as its parameter -#. ``fromBlock`` - ``string`` (optional): get all events from this block, defaults to ``latest`` - -------- -Returns -------- - -``Promise`` resolves to ``string``: event subscription. - -------- -Example -------- - -.. code-block:: javascript - - // subscribe to the 'ContractEvent' at the EventHub located at '00000000000000000000000000000000deadbeef' - runtime.eventHub - .once( - 'EventHub', - '00000000000000000000000000000000deadbeef', - 'ContractEvent', - (event) => true, - (event) => { - console.dir(event) - } - ) - .then((result) => { subscription = result; }) - ------------------------------------------------------------------------------- - - -.. _eventhub_unsubscribe: - -unsubscribe -=================== - -.. code-block:: javascript - - eventHub.unsubscribe(toRemove); - -unsubscribe an event subscription - ----------- -Parameters ----------- - -#. ``contractName`` - ``string``: target contract name (must be available within |source contractLoader|_ ) - * ``subscription`` - ``string``: target guid for the subscription that should be removed - * ``contractId`` - ``string``: target contractId where all subscriptions should be removed (can be 'all') - -------- -Returns -------- - -``Promise`` resolves to ``void``: resolved when done. - -------- -Example -------- - -.. code-block:: javascript - - // subscribe to the 'ContractEvent' at the EventHub located at '00000000000000000000000000000000deadbeef' - runtime.eventHub - .unsubscribe({ - subscription: 'f0315d39-5e03-4e82-b765-df1c03037b3a' - }) - - -.. required for building markup - -.. |source contractLoader| replace:: ``ContractLoader`` -.. _source contractLoader: /contracts/contract-loader.html - -.. |source logLevel| replace:: ``LogLevel`` -.. _source logLevel: /common/logger.html#loglevel - -.. |source logLogInterface| replace:: ``LogLogInterface`` -.. _source logLogInterface: /common/logger.html#logloginterface - -.. |source nameResolver| replace:: ``NameResolver`` -.. _source nameResolver: /blockchain/name-resolver.html - -.. |source web3| replace:: ``Web3`` -.. _source web3: https://github.com/ethereum/web3.js/ diff --git a/docs/blockchain/executor-agent.rst b/docs/blockchain/executor-agent.rst new file mode 100644 index 00000000..68ba398c --- /dev/null +++ b/docs/blockchain/executor-agent.rst @@ -0,0 +1,476 @@ +================================================================================ +ExecutorAgent +================================================================================ + +.. list-table:: + :widths: auto + :stub-columns: 1 + + * - Class Name + - ExecutorAgent + * - Extends + - `Executor <../blockchain/executor.html>`_ + * - Source + - `executor-agent.ts `_ + * - Examples + - `executor-agent.spec.ts `_ + + +The ``ExecutorAgent`` module is designed to cover basically the same tasks as the `Executor <../blockchain/executor.html>`_ module. While the last one performs the transactions directly with an account, that is given as inputOptions, the ``ExecutorAgent`` module wraps those transactions by submitting them to a smart agent. + +The smart agent receives those transactions and performs them with its own account, if a valid tokens has been passed to it alongside the transaction data. Tokens for transactions can be issued at the smart agent as well (a password is required for this). + +Using the ``ExecutorAgent`` allows to delegate transactions to users that do not have their own blockchain accounts. Delegating those transactions requires that smart agent user to be invited into the contract instead of the users, that will interact with the contract. + +Users without accounts are then interacting with the front-end the same way as regular users, but do not submit their transactions themselves, they make a REST request against a smart agent server. To prevent spamming and scamming, the users use tokens for their transactions. Tokens are basically like prepaid telephone card and allows to perform a limited set of functions for a limited amount of times. Tokens can only be created with a valid password. + +Let's say, we have created a `DataContract `_, that contains three questions, that should be answered by someone without an own blockchain account (think of a customer survey or something similar). + +To allow that, first invite the corresponding smart agent account into the contract. Smart agent accounts for this should be known to the party, that wants to delegate transactions and their funds are maintained by this party, we'll use an example address for this here. + +For abbreviation we assume, we have the following values: + +.. code-block:: typescript + + let dataContractInstance; // our data contract with the survey questions + let contractOwner; // 'we' - the contract creator and owner + let businessCenterDomain = 'testbc.evan'; // contracts business center + let smartAgentId; // account id of our smart agent + let password; // password, for token generation + +So let's invite the smart agent to our contract: + +.. code-block:: typescript + + await dataContract.inviteToContract( + businessCenterDomain, + dataContractInstance.options.address, + contractOwner, + smartAgentId, + ); + +Now with the smart agent being able to perform transactions, create a token for transaction delegation. We want the user to be able to: + +#. accept the invitation +#. write three answers +#. mark their state as "done" + +.. code-block:: typescript + + const txToken = await executor.generateToken( + password, [ + { contract: dataContractInstance, functionName: 'changeConsumerState', count: 2, }, + { contract: dataContractInstance, functionName: 'addListEntry', count: 3, }, + ]); + +Allowing ``addListEntry`` three time is to allow them to write three answers. One of the ``changeConsumerState`` times is for accepting the contract, which is done by setting the own state to ``Active``. The other one is for marking editing as done (setting the own state to ``Terminated``). + +The resulting token ``txToken`` is a string, that can be handed over to our users without an account. This is usually done by sending them an email with a link, that contains the token and skips the login step for them and routes them directly to the contract, they should respond to. + +Let's switch sides. The next steps are performed in the front-end by a user without a blockchain account, that has received the token. + +To make transaction via a smart agent, create an instance of the ``ExecutorWallet`` and assign the token from before as ``token`` . + +.. code-block:: typescript + + const executor = new ExecutorAgent({ + agentUrl + config, + eventHub, + signer, + web3 + }); + executor.token = txToken; + +To use the ``ExecutorWallet`` instance created this way in your other modules, hand it over to their contstructor like instead of a normal ``Executor`` instance. Then use your modules, that have the ``ExeutorWallet`` instance like you would use them for making transactions with your own account. + +.. code-block:: typescript + + const surveyAnswer = { + foo: 'sample', + bar: 123, + }; + await dataContract.addListEntries(dataContractInstance, ['surveyAnswers'], [sampleValue], smartAgentId); + +Note, that the last sample uses the smartAgentId as the performing account. Because transactions are estimated before being executed and in some cases the underlying modules require an "active" account, that is used as the users identity, this has to match the smart agents account id. The smart agent account id is passed alongside the token via the link in the email for users wihtout blockchain accounts. References, that would point to a users account have to be replaced with this smart agent account id. + + +.. figure:: ../_static/agent_tx_transparent.png + :align: center + :alt: transaction flow in agent based transactions + + transaction flow in agent based transactions + + +.. _executor_agent_constructor: + +constructor +================================================================================ + +.. code-block:: typescript + + new ExecutorAgent(options); + +Creates a new ExecutorAgent instance. + +The ExecutorAgent allows to pass the ``defaultOptions`` property to its constructor. This property contains options for transactions and calls, that will be used if no other properties are provided in calls/transactions. Explicitly passed options always overwrite default options. + +---------- +Parameters +---------- + +#. ``options`` - ``ExecutorAgentOptions``: options for ServiceContract constructor. + * ``config`` - ``any``: configuration object for the executor instance + * ``defaultOptions`` - ``any`` (optional): default options for web3 transactions/calls + * ``eventHub`` - |source eventHub|_: |source eventHub|_ instance + * ``signer`` - |source signerInterface|_: |source signerInterface|_ instance + * ``web3`` - |source web3|_: |source web3|_ instance + * ``agentUrl`` - ``string`` (optional): agent url, including protocol, host and port, defaults to ``'http://localhost:8080'`` + * ``log`` - ``Function`` (optional): function to use for logging: ``(message, level) => {...}`` + * ``logLevel`` - |source logLevel|_ (optional): messages with this level will be logged with ``log`` + * ``logLog`` - |source logLogInterface|_ (optional): container for collecting log messages + * ``logLogLevel`` - |source logLevel|_ (optional): messages with this level will be pushed to ``logLog`` + +------- +Returns +------- + +``ExecutorAgent`` instance + +------- +Example +------- + +.. code-block:: typescript + + const executor = new ExecutorAgent({ + agentUrl + config, + eventHub, + signer, + web3 + }); + + + +-------------------------------------------------------------------------------- + +.. _executor_agent_init: + +init +=================== + +.. code-block:: javascript + + executor.init(name); + +initialize executor + +---------- +Parameters +---------- + +#. ``options`` - ``any``: object with the property "eventHub" (of the type EventHub) + * ``eventHub`` - ``EventHub``: The initialized EventHub Module. + +------- +Returns +------- + +``void``. + +------- +Example +------- + +.. code-block:: javascript + + runtime.executor.init({eventHub: runtime.eventHub}) + +------------------------------------------------------------------------------ + +.. _executor_agent_executeContractCall: + +executeContractCall +=================== + +.. code-block:: javascript + + executor.executeContractCall(contract, functionName, ...args); + +run the given call from contract + +this is done as a rest call against the smart agent + +a token is not required for performing calls + +---------- +Parameters +---------- + +#. ``contract`` - ``any``: the target contract +#. ``functionName`` - ``string``: name of the contract function to call +#. ``...args`` - ``any[]``: optional array of arguments for contract call. if last arguments is {Object}, it is used as the options parameter + +------- +Returns +------- + +``Promise`` resolves to ``any``: contract calls result. + +------- +Example +------- + +.. code-block:: javascript + + const greetingMessage = await runtime.executor.executeContractCall( + contract, // web3.js contract instance + 'greet' // function name + ); + +------------------------------------------------------------------------------ + +.. _executor_agent_executeContractTransaction: + +executeContractTransaction +========================== + +.. code-block:: javascript + + executor.executeContractTransaction(contract, functionName, inputOptions, ...functionArguments); + +execute a transaction against the blockchain, handle gas exceeded and return values from contract function + +this is done as a rest call against the smart agent + +transactions, that transfer EVEs to a target account, will be rejected + +this requires a valid token issued with ``generateToken`` beforehand, tokens can be set at the executor with: + +.. code-block:: javascript + + executor.token = someToken; + +---------- +Parameters +---------- + +#. ``contract`` - ``any``: contract instance +#. ``functionName`` - ``string``: name of the contract function to call +#. ``inputOptions`` - ``any``: options object + * ``from`` - ``string`` (optional): The address the call "transaction" should be made from. + * ``gas`` - ``number`` (optional): The amount of gas provided with the transaction. + * ``event`` - ``string`` (optional): The event to wait for a result of the transaction, + * ``getEventResult`` - ``function`` (optional): callback function which will be called when the event is triggered. + * ``eventTimeout`` - ``number`` (optional): timeout (in ms) to wait for a event result before the transaction is marked as error + * ``estimate`` - ``boolean`` (optional): Should the amount of gas be estimated for the transaction (overwrites ``gas`` parameter) + * ``force`` - ``string`` (optional): Forces the transaction to be executed. Ignores estimation errors + * ``autoGas`` - ``number`` (optional): enables autoGas 1.1 ==> adds 10% to estimated gas costs. value capped to current block. +#. ``...functionArguments`` - ``any[]``: optional arguments to pass to contract transaction + +------- +Returns +------- + +``Promise`` resolves to: ``no result`` (if no event to watch was given), ``the event`` (if event but no getEventResult was given), ``the`` value returned by getEventResult(eventObject). + +Because an estimation is performed, even if a fixed gas cost has been set, failing transactions are rejected before being executed. This protects users from executing transactions, that consume all provided gas and fail, which is usually not intended, especially if a large amount of gas has been provided. To prevent this behavior for any reason, add a ``force: true`` to the options, though it is **not advised to do so**. + +To allow to retrieve the result of a transaction, events can be used to receive values from a transaction. If an event is provided, the transaction will only be fulfilled, if the event is triggered. To use this option, the executor needs to have the ``eventHub`` property has to be set. Transactions, that contain event related options and are passed to an executor without an ``eventHub`` will be rejected immediately. + +------- +Example +------- + +.. code-block:: javascript + + const accountId = '0x...'; + const greetingMessage = await runtime.executor.executeContractTransaction( + contract, // web3.js contract instance + 'setData', // function name + { from: accountId, }, // perform transaction with this account + 123, // arguments after the options are passed to the contract + ); + +Provided gas is estimated automatically with a fault tolerance of 10% and then used as `gas` limit in the transaction. For a different behavior, set `autoGas` in the transaction options: + +.. code-block:: javascript + + const greetingMessage = await runtime.executor.executeContractTransaction( + contract, // web3.js contract instance + 'setData', // function name + { from: accountId, autoGas: 1.05, }, // 5% fault tolerance + 123, // arguments after the options are passed to the contract + ); + +or set a fixed gas limit: + +.. code-block:: javascript + + const greetingMessage = await runtime.executor.executeContractTransaction( + contract, // web3.js contract instance + 'setData', // function name + { from: accountId, gas: 100000, }, // fixed gas limit + 123, // arguments after the options are passed to the contract + ); + +Using events for getting return values: + +.. code-block:: javascript + + const contractId = await runtime.executor.executeContractTransaction( + factory, + 'createContract', { + from: accountId, + autoGas: 1.1, + event: { target: 'FactoryInterface', eventName: 'ContractCreated', }, + getEventResult: (event, args) => args.newAddress, + }, + ); + + +------------------------------------------------------------------------------ + + + +.. _executor_agent_executeSend: + +executeSend +=================== + +.. code-block:: javascript + + executor.executeSend(options); + +**creating contracts directly is not supported by the walled based executor, use a regular Executor for such tasks** + +------------------------------------------------------------------------------ + + + +.. _executor_agent_createContract: + +createContract +=================== + +.. code-block:: javascript + + executor.createContract(contractName, functionArguments, options); + +creates a contract by contstructing creation transaction and signing it with private key of options.from + +this is done as a rest call against the smart agent + +transactions, that transfer EVEs to a target account, will be rejected + +this requires a valid token issued with ``generateToken`` beforehand, tokens can be set at the executor with: + +.. code-block:: javascript + + executor.token = someToken; + +---------- +Parameters +---------- + +#. ``contractName`` - ``string``: contract name (must be available withing contract loader module) +#. ``functionArguments`` - ``any[]``: arguments for contract creation, pass empty Array if no arguments +#. ``options`` - ``any``: options object + * ``from`` - ``string``: The address the call "transaction" should be made from. + * ``gas`` - ``number``: Provided gas amout for contract creation. + +------- +Returns +------- + +``Promise`` resolves to ``any``: new contract. + +------- +Example +------- + +.. code-block:: javascript + + const newContractAddress = await runtime.executor.createContract( + 'Greeter', // contract name + ['I am a demo greeter! :3'], // constructor arguments + { from: '0x...', gas: 100000, }, // gas has to be provided with a fixed value + ); + + + + +-------------------------------------------------------------------------------- + +.. _executor_agent_generateToken: + +generateToken +================================================================================ + +.. code-block:: typescript + + executor.generateToken(password, functions); + +generate a new token for transactions (or contract creations) + +this generates a new token for the given functions, this token can be used for each requested function (either only once or multiple times, if a count > 1 has been requested) + +---------- +Parameters +---------- + +#. ``password`` - ``string``: password for token creation +#. ``functions`` - ``any[]``: array of function signatures as abi objects + +------- +Returns +------- + +``Promise`` returns ``string``: token for given transactions + +------- +Example +------- + +Tokens can be created for transactions by passing the contract and the function name to it: + +.. code-block:: typescript + + const txToken = await executor.generateToken( + password, [{ contract: contract, functionName: 'addListEntry', }]); + +When the token should be able to perform those transactions multiple times, pass a count alongside: + +.. code-block:: typescript + + const txToken = await executor.generateToken( + password, [{ contract: contract, functionName: 'addListEntry', count: 3, }]); + +When wanting to perform a contract creation without a factory contract, this contract has to be known to the smart agent. Then the contract name can be passed as 'signature': + +.. code-block:: typescript + + cosnt ccToken = await executor.generateToken( + password, [{ signature: 'Owned', }]); + + + +.. required for building markup +.. |source dataContract| replace:: ``DataContract`` +.. _source dataContract: /contracts/data-contract.html + +.. |source eventHub| replace:: ``EventHub`` +.. _source eventHub: /blockchain/event-hub.html + +.. |source logLevel| replace:: ``LogLevel`` +.. _source logLevel: /common/logger.html#loglevel + +.. |source logLogInterface| replace:: ``LogLogInterface`` +.. _source logLogInterface: /common/logger.html#logloginterface + +.. |source signerInterface| replace:: ``SignerInterface`` +.. _source signerInterface: /blockchain/signer.html + +.. |source web3| replace:: ``Web3`` +.. _source web3: https://github.com/ethereum/web3.js/ diff --git a/docs/blockchain/executor.rst b/docs/blockchain/executor-wallet.rst similarity index 71% rename from docs/blockchain/executor.rst rename to docs/blockchain/executor-wallet.rst index 7ffca8b1..da77b973 100644 --- a/docs/blockchain/executor.rst +++ b/docs/blockchain/executor-wallet.rst @@ -1,5 +1,5 @@ ================================================================================ -Executor +ExecutorWallet ================================================================================ .. list-table:: @@ -7,52 +7,52 @@ Executor :stub-columns: 1 * - Class Name - - Executor + - ExecutorWallet * - Extends - - `Logger `_ + - `Executor <../blockchain/executor.html>`_ * - Source - - `executor.ts `_ - * - Tests - - `executor.spec.ts `_ + - `executor-wallet.ts `_ + * - Examples + - `executor-wallet.spec.ts `_ -The executor is used for +The ``ExecutorWallet`` module is designed to cover basically the same tasks as the |source executor|_ module. While the last one performs the transactions directly with an account, that is given as inputOptions, the ``ExecutorWallet`` module wraps those transactions by sumitting them to a configured wallet contract. -- making contract calls -- executing contract transactions -- creating contracts -- send EVEs to another account or contract +.. figure:: ../_static/wallet_tx_transparent.png + :align: center + :alt: transaction flow in wallet based transactions -The signer requires you to have a contract instance, either by + transaction flow in wallet based transactions -- loading the contract via `Description `_ helper (if the contract has an abi at its description) -- loading the contract via `ContractLoader `_ helper (if the contract has not abi at its description) -- directly via `web3.js `_. +The wallet is a smart contract and the account, that performs the transactions against the target contracts on the blockchain. Transactions are wrapped by using the |source wallet|_ module, see details on how to transactions are performed internally at the documentation page of the |source wallet|_ module. +Because transactions are performed via the |source wallet|_ module, they have the same limitations in regards to en- and decryption as described in the introduction section of the |source wallet|_. -.. _executor_constructor: + +.. _executor_wallet_constructor: constructor ================================================================================ .. code-block:: typescript - new Executor(options); + new ExecutorWallet(options); -Creates a new Executor instance. +Creates a new ``ExecutorWallet`` instance. -The Executor allows to pass the ``defaultOptions`` property to its constructor. This property contains options for transactions and calls, that will be used if no other properties are provided in calls/transactions. Explicitly passed options always overwrite default options. +The ExecutorWallet allows to pass the ``defaultOptions`` property to its constructor. This property contains options for transactions and calls, that will be used if no other properties are provided in calls/transactions. Explicitly passed options always overwrite default options. ---------- Parameters ---------- -#. ``options`` - ``ExecutorOptions``: options for ServiceContract constructor. +#. ``options`` - ``ExecutorWalletOptions``: options for ServiceContract constructor. * ``config`` - ``any``: configuration object for the executor instance - * ``defaultOptions`` - ``any`` (optional): default options for web3 transactions/calls * ``eventHub`` - |source eventHub|_: |source eventHub|_ instance * ``signer`` - |source signerInterface|_: |source signerInterface|_ instance + * ``wallet`` - |source wallet|_: |source wallet|_ instance with a loaded wallet contract * ``web3`` - |source web3|_: |source web3|_ instance + * ``defaultOptions`` - ``any`` (optional): default options for web3 transactions/calls * ``log`` - ``Function`` (optional): function to use for logging: ``(message, level) => {...}`` * ``logLevel`` - |source logLevel|_ (optional): messages with this level will be logged with ``log`` * ``logLog`` - |source logLogInterface|_ (optional): container for collecting log messages @@ -62,7 +62,7 @@ Parameters Returns ------- -``Executor`` instance +``ExecutorWallet`` instance ------- Example @@ -70,10 +70,11 @@ Example .. code-block:: typescript - const executor = new Executor({ + const executor = new ExecutorWallet({ config, eventHub, signer, + wallet, web3 }); @@ -81,7 +82,7 @@ Example -------------------------------------------------------------------------------- -.. _executor_init: +.. _executor_wallet_init: init =================== @@ -115,7 +116,7 @@ Example ------------------------------------------------------------------------------ -.. _executor_executeContractCall: +.. _executor_wallet_executeContractCall: executeContractCall =================== @@ -124,7 +125,9 @@ executeContractCall executor.executeContractCall(contract, functionName, ...args); -gets contract from a solc compilation +run the given call from contract + +note, that if a from is used, this from is replaced with the wallets address ---------- Parameters @@ -153,7 +156,9 @@ Example ------------------------------------------------------------------------------ -.. _executor_executeContractTransaction: + + +.. _executor_wallet_executeContractTransaction: executeContractTransaction ========================== @@ -162,7 +167,9 @@ executeContractTransaction executor.executeContractTransaction(contract, functionName, inputOptions, ...functionArguments); -execute a transaction against the blockchain, handle gas exceeded and return values from contract function +execute a transaction against the blockchain, handle gas exceeded and return values from contract function, + +note, that a from passed to this function will be replaced with the wallets address and that transactions, that transfer EVEs to a target account, will be rejected ---------- Parameters @@ -246,7 +253,7 @@ Using events for getting return values: -.. _executor_executeSend: +.. _executor_wallet_executeSend: executeSend =================== @@ -255,39 +262,14 @@ executeSend executor.executeSend(options); -send EVEs to target account - ----------- -Parameters ----------- - -#. ``options`` - ``any``: the target contract - * ``from`` - ``string``: The address the call "transaction" should be made from. - * ``to`` - ``string``: The address where the eve's should be send to. - * ``value`` - ``number``: Amount to send in Wei +**sending funds is not supported by the walled based executor, use a regular Executor for such tasks** -------- -Returns -------- - -``Promise`` resolves to ``void``: resolved when done. - -------- -Example -------- - -.. code-block:: javascript - - await runtime.executor.executeSend({ - from: '0x...', // send from this account - to: '0x...', // receiving account - value: web3.utils.toWei('1'), // amount to send in Wei - }); ------------------------------------------------------------------------------ -.. _executor_createContract: + +.. _executor_wallet_createContract: createContract =================== @@ -296,52 +278,28 @@ createContract executor.createContract(contractName, functionArguments, options); -creates a contract by contstructing creation transaction and signing it with private key of options.from - ----------- -Parameters ----------- - -#. ``contractName`` - ``string``: contract name (must be available withing contract loader module) -#. ``functionArguments`` - ``any[]``: arguments for contract creation, pass empty Array if no arguments -#. ``options`` - ``any``: options object - * ``from`` - ``string``: The address the call "transaction" should be made from. - * ``gas`` - ``number``: Provided gas amout for contract creation. - -------- -Returns -------- - -``Promise`` resolves to ``any``: new contract. - -------- -Example -------- - -.. code-block:: javascript - - const newContractAddress = await runtime.executor.createContract( - 'Greeter', // contract name - ['I am a demo greeter! :3'], // constructor arguments - { from: '0x...', gas: 100000, }, // gas has to be provided with a fixed value - ); +**creating contracts directly is not supported by the walled based executor, use a regular Executor for such tasks** .. required for building markup - - .. |source signerInterface| replace:: ``SignerInterface`` .. _source signerInterface: /blockchain/signer.html .. |source eventHub| replace:: ``EventHub`` .. _source eventHub: /blockchain/event-hub.html +.. |source executor| replace:: ``Executor`` +.. _source executor: /blockchain/executor.html + .. |source logLevel| replace:: ``LogLevel`` .. _source logLevel: /common/logger.html#loglevel .. |source logLogInterface| replace:: ``LogLogInterface`` .. _source logLogInterface: /common/logger.html#logloginterface +.. |source wallet| replace:: ``Wallet`` +.. _source wallet: /blockchain/wallet.html + .. |source web3| replace:: ``Web3`` .. _source web3: https://github.com/ethereum/web3.js/ \ No newline at end of file diff --git a/docs/blockchain/index.rst b/docs/blockchain/index.rst index 07783a61..e602c570 100644 --- a/docs/blockchain/index.rst +++ b/docs/blockchain/index.rst @@ -7,11 +7,14 @@ Blockchain :maxdepth: 1 executor + executor-agent + executor-wallet signer account-store event-hub name-resolver description + wallet This section contains modules, that deal with basic blockchain interactions, like diff --git a/docs/blockchain/name-resolver.rst b/docs/blockchain/name-resolver.rst deleted file mode 100644 index 7cf0addc..00000000 --- a/docs/blockchain/name-resolver.rst +++ /dev/null @@ -1,588 +0,0 @@ -================================================================================ -Name Resolver -================================================================================ - -.. list-table:: - :widths: auto - :stub-columns: 1 - - * - Class Name - - NameResolver - * - Extends - - `Logger `_ - * - Source - - `name-resolver.ts `_ - * - Tests - - `name-resolver.spec.ts `_ - -The `NameResolver `_ is a collection of helper functions, that can be used for ENS interaction. These include: - -- setting and getting ENS addresses -- setting and getting ENS content flags, which is used when setting data in distributed file system, especially in case of setting a description for an `ENS` address - -.. _name_resolver_constructor: - -constructor -================================================================================ - -.. code-block:: typescript - - new NameResolver(options); - -Creates a new NameResolver instance. - ----------- -Parameters ----------- - -#. ``options`` - ``NameResolverOptions``: options for NameResolver constructor. - * ``config`` - ``any``: configuration object for the NameResolver instance - * ``executor`` - |source executor|_: |source executor|_ instance - * ``contractLoader`` - |source contractLoader|_: |source contractLoader|_ instance - * ``web3`` - |source web3|_: |source web3|_ instance - * ``log`` - ``Function`` (optional): function to use for logging: ``(message, level) => {...}`` - * ``logLevel`` - |source logLevel|_ (optional): messages with this level will be logged with ``log`` - * ``logLog`` - |source logLogInterface|_ (optional): container for collecting log messages - * ``logLogLevel`` - |source logLevel|_ (optional): messages with this level will be pushed to ``logLog`` - -------- -Returns -------- - -``NameResolver`` instance - -------- -Example -------- - -.. code-block:: typescript - - const nameResolver = new NameResolver({ - cryptoProvider, - dfs, - executor, - keyProvider, - nameResolver, - contractLoader, - web3, - }); - - - --------------------------------------------------------------------------------- - -.. _name_resolver_getAddressOrContent: - -getAddressOrContent -=================== - -.. code-block:: javascript - - nameResolver.getAddressOrContent(name, type); - -get address or content of an ens entry - ----------- -Parameters ----------- - -#. ``name`` - ``string``: ens domain name (plain text) -#. ``type`` - ``string``: content type to get (address or content) - -------- -Returns -------- - -``Promise`` resolves to ``string``: address, returns null if not available - -------- -Example -------- - -.. code-block:: javascript - - const testEvanAddress = await runtime.nameResolver.getAddressOrContent('test.evan', 'address'); - // returns 0x9c0Aaa728Daa085Dfe85D3C72eE1c1AdF425be49 - ------------------------------------------------------------------------------- - -.. _name_resolver_getAddress: - -getAddress -=================== - -.. code-block:: javascript - - nameResolver.getAddress(name); - -get address of an ens entry - ----------- -Parameters ----------- - -#. ``name`` - ``string``: ens domain name (plain text) - -------- -Returns -------- - -``Promise`` resolves to ``string``: address, returns null if not available - -------- -Example -------- - -.. code-block:: javascript - - const testEvanAddress = await runtime.nameResolver.getAddress('test.evan'); - // returns 0x9c0Aaa728Daa085Dfe85D3C72eE1c1AdF425be49 - ------------------------------------------------------------------------------- - -.. _name_resolver_getContent: - -getContent -=================== - -.. code-block:: javascript - - nameResolver.getContent(name); - -get content of an ens entry - ----------- -Parameters ----------- - -#. ``name`` - ``string``: ens domain name (plain text) - -------- -Returns -------- - -``Promise`` resolves to ``string``: content, returns null if not available - -------- -Example -------- - -.. code-block:: javascript - - const testEvanAddress = await runtime.nameResolver.getContent('test.evan'); - // returns (encoded ipfs hash) 0x9c0Aaa728Daa085Dfe85D3C72eE1c1AdF425be49 - ------------------------------------------------------------------------------- - -.. _name_resolver_setAddressOrContent: - -setAddressOrContent -=================== - -.. code-block:: javascript - - nameResolver.setAddressOrContent(name, value, accountId, domainOwnerId, type); - -set ens name. this can be a root level domain domain.test or a subdomain sub.domain.test - ----------- -Parameters ----------- - -#. ``name`` - ``string``: ens domain name (plain text) -#. ``value`` - ``string``: ethereum address -#. ``accountId`` - ``string``: owner of the parent domain -#. ``domainOwnerId`` - ``string``: owner of the address to set -#. ``type`` - ``string``: content type to set - -------- -Returns -------- - -``Promise`` resolves to ``void``: resolves when done - -------- -Example -------- - -.. code-block:: javascript - - const testEvanAddress = await runtime.nameResolver - .setAddressOrContent( - 'test.evan', - '0x9c0Aaa728Daa085Dfe85D3C72eE1c1AdF425be49', - '0x000000000000000000000000000000000000beef', - '0x000000000000000000000000000000000000beef', - 'address' - ); - // returns (encoded ipfs hash) 0x9c0Aaa728Daa085Dfe85D3C72eE1c1AdF425be49 - ------------------------------------------------------------------------------- - -.. _name_resolver_setAddress: - -setAddress -=================== - -.. code-block:: javascript - - nameResolver.setAddress(name, address, accountId, domainOwnerId); - -set address for ens name. this can be a root level domain domain.test or a subdomain sub.domain.test - ----------- -Parameters ----------- - -#. ``name`` - ``string``: ens domain name (plain text) -#. ``address`` - ``string``: ethereum address -#. ``accountId`` - ``string``: owner of the parent domain -#. ``domainOwnerId`` - ``string``: owner of the address to set - -------- -Returns -------- - -``Promise`` resolves to ``void``: resolves when done - -------- -Example -------- - -.. code-block:: javascript - - const testEvanAddress = await runtime.nameResolver - .setAddress( - 'test.evan', - '0x9c0Aaa728Daa085Dfe85D3C72eE1c1AdF425be49', - '0x000000000000000000000000000000000000beef', - '0x000000000000000000000000000000000000beef' - ); - ------------------------------------------------------------------------------- - - -.. _name_resolver_setContent: - -setContent -=================== - -.. code-block:: javascript - - nameResolver.setContent(name, content, accountId, domainOwnerId); - -set content for ens name. this can be a root level domain domain.test or a subdomain sub.domain.test - ----------- -Parameters ----------- - -#. ``name`` - ``string``: ens domain name (plain text) -#. ``content`` - ``string``: ethereum address -#. ``accountId`` - ``string``: owner of the parent domain -#. ``domainOwnerId`` - ``string``: owner of the address to set - -------- -Returns -------- - -``Promise`` resolves to ``void``: resolves when done - -------- -Example -------- - -.. code-block:: javascript - - const testEvanAddress = await runtime.nameResolver - .setContent( - 'test.evan', - '0x9c0Aaa728Daa085Dfe85D3C72eE1c1AdF425be49', - '0x000000000000000000000000000000000000beef', - '0x000000000000000000000000000000000000beef' - ); - ------------------------------------------------------------------------------- - -.. _name_resolver_getFactory: - -getFactory -=================== - -.. code-block:: javascript - - nameResolver.getFactory(contractName); - -helper function for retrieving a factory address (e.g. 'tasks.factory.evan') - ----------- -Parameters ----------- - -#. ``contractName`` - ``string``: name of the contract that is created by the factory - -------- -Returns -------- - -``string``: address of the contract factory - -------- -Example -------- - -.. code-block:: javascript - - const taskFactory = await runtime.nameResolver.getFactory('tasks'); - // returns '0x9c0Aaa728Daa085Dfe85D3C72eE1c1AdF425be49'; - ------------------------------------------------------------------------------- - -.. _name_resolver_getDomainName: - -getDomainName -=================== - -.. code-block:: javascript - - nameResolver.getDomainName(domainConfig, ...subLabels); - -builds full domain name based on the provided domain config a module initalization. - ----------- -Parameters ----------- - -#. ``domainConfig`` - ``string[] | string``: The domain configuration -#. ``...subLabels`` - ``string[]``: array of domain elements to be looked up and added at the lefthand - -------- -Returns -------- - -``string``: the domain name - -------- -Example -------- - -.. code-block:: javascript - - const domain = runtime.nameResolver.getDomainName(['factory', 'root'], 'task'); - // returns 'task.factory.evan'; - ------------------------------------------------------------------------------- - -.. _name_resolver_getArrayFromIndexContract: - -getArrayFromIndexContract -========================= - -.. code-block:: javascript - - nameResolver.getArrayFromIndexContract(indexContract, listHash, retrievers, chain, triesLeft); - -retrieve an array with all values of a list from an index contract. - ----------- -Parameters ----------- - -#. ``indexContract`` - ``any``: Ethereum contract address (DataStoreIndex) -#. ``listHash`` - ``string``: bytes32 namehash like api.nameResolver.sha3('ServiceContract') -#. ``retrievers`` - ``any`` (optional): overwrites for index or index like contract property retrievals defaults to: - -.. code-block:: javascript - - { - listEntryGet: 'listEntryGet', - listLastModified: 'listLastModified', - listLength: 'listLength', - } - -#. ``chain`` - ``Promise``: Promise, for chaining multiple requests (should be omitted when called 'from outside', defaults to Promise.resolve()) -#. ``triesLeft`` - ``number``: tries left before quitting defaults to ``10`` - -------- -Returns -------- - -``Promise`` resolves to ``string[]``: list of addresses - ------------------------------------------------------------------------------- - -.. _name_resolver_getArrayFromListContract: - -getArrayFromListContract -======================== - -.. code-block:: javascript - - nameResolver.getArrayFromListContract(indexContract, count, offset, reverse, chain, triesLeft); - -retrieve an array with all values of a list from an index contract. - ----------- -Parameters ----------- - -#. ``indexContract`` - ``any``: Ethereum contract address (DataStoreIndex) -#. ``count`` - ``number`` (optional): how many items should be returned, defaults to ``10`` -#. ``offset`` - ``number`` (optional): how many items should be skipped, defaults to ``0`` -#. ``reverse`` - ``boolean`` (optional): should the list be iterated reverse, defaults to ``false`` -#. ``chain`` - ``Promise`` (optional): Promise, for chaining multiple requests (should be omitted when called 'from outside', defaults to Promise.resolve()) -#. ``triesLeft`` - ``number`` (optional): tries left before quitting defaults to ``10`` - -------- -Returns -------- - -``Promise`` resolves to ``string[]``: list of addresses - ------------------------------------------------------------------------------- - -.. _name_resolver_getArrayFromUintMapping: - -getArrayFromUintMapping -======================= - -.. code-block:: javascript - - nameResolver.getArrayFromUintMapping(contract, countRetriever, elementRetriever[, count, offset, reverse]); - -retrieve elements from a contract using a count and element retriever function. - ----------- -Parameters ----------- - -#. ``contract`` - ``any``: Ethereum contract address (DataStoreIndex) -#. ``countRetriever`` - ``Function`` : function which returns the count of the retrieved elements -#. ``elementRetriever`` - ``Function`` : function which returns the element of the retrieved elements -#. ``count`` - ``number`` (optional): number of elements to retrieve, defaults to ``10`` -#. ``offset`` - ``number`` (optional): skip this many items when retrieving, defaults to ``0`` -#. ``reverse`` - ``boolean`` (optional): retrieve items in reverse order, defaults to ``false`` - -------- -Returns -------- - -``Promise`` resolves to ``string[]``: list of addresses - ------------------------------------------------------------------------------- - -.. _name_resolver_sha3: - -sha3 -=================== - -.. code-block:: javascript - - nameResolver.sha3(input); - -sha3 hashes an input, substitutes web3.utils.sha3 from geth console - ----------- -Parameters ----------- - -#. ``input`` - ``string | buffer``: input text or buffer to hash - -------- -Returns -------- - -``string``: hashed output - ------------------------------------------------------------------------------- - -.. _name_resolver_soliditySha3: - -soliditySha3 -=================== - -.. code-block:: javascript - - nameResolver.soliditySha3(...args); - -Will calculate the sha3 of given input parameters in the same way solidity would. This means arguments will be ABI converted and tightly packed before being hashed. - ----------- -Parameters ----------- - -#. ``args`` - ``string | buffer``: arguments for hashing - -------- -Returns -------- - -``string``: hashed output - ------------------------------------------------------------------------------- - -.. _name_resolver_namehash: - -namehash -=================== - -.. code-block:: javascript - - nameResolver.namehash(inputName); - -hash ens name for usage in contracts - ----------- -Parameters ----------- - -#. ``inputName`` - ``string``: inputName ens name to hash - -------- -Returns -------- - -``string``: name hash - ------------------------------------------------------------------------------- - -.. _name_resolver_bytes32ToAddress: - -bytes32ToAddress -=================== - -.. code-block:: javascript - - nameResolver.bytes32ToAddress(hash); - -converts a bytes32 hash to address - ----------- -Parameters ----------- - -#. ``hash`` - ``string``: bytes32 hash - -------- -Returns -------- - -``string``: converted address - - -.. required for building markup - -.. |source executor| replace:: ``Executor`` -.. _source executor: /blockchain/executor.html - -.. |source contractLoader| replace:: ``ContractLoader`` -.. _source contractLoader: /contracts/contract-loader.html - -.. |source logLevel| replace:: ``LogLevel`` -.. _source logLevel: /common/logger.html#loglevel - -.. |source logLogInterface| replace:: ``LogLogInterface`` -.. _source logLogInterface: /common/logger.html#logloginterface - -.. |source web3| replace:: ``Web3`` -.. _source web3: https://github.com/ethereum/web3.js/ \ No newline at end of file diff --git a/docs/blockchain/signer.rst b/docs/blockchain/signer.rst deleted file mode 100644 index cafd5bf3..00000000 --- a/docs/blockchain/signer.rst +++ /dev/null @@ -1,308 +0,0 @@ -================================================================================ -Signer -================================================================================ - -.. list-table:: - :widths: auto - :stub-columns: 1 - - * - Class Name - - SignerInternal - * - Implements - - `SignerInterface `_ - * - Extends - - `Logger `_ - * - Source - - `signer-internal.ts `_ - -The signers are used to create contract transactions and are used internally by the `Executor `_. The default runtime uses the `SignerInternal `_ helper to sign transaction. - -In most cases, you won't have to use the Signer objects directly yourself, as the `Executor `_ is your entry point for performing contract transactions. - ------------------------------------------------------------------------------- - -.. _signer_constructor: - -constructor -================================================================================ - -.. code-block:: typescript - - new SignerInternal(options); - -Creates a new SignerInternal instance. - ----------- -Parameters ----------- - -#. ``options`` - ``SignerInternalOptions``: options for SignerInternal constructor. - * ``accountStore`` - |source keyStoreinterface|_: |source keyStoreinterface|_ instance - * ``config`` - ``any``: signer internal configuration - * ``contractLoader`` - |source contractLoader|_: |source contractLoader|_ instance - * ``web3`` - |source web3|_: |source web3|_ instance - * ``log`` - ``Function`` (optional): function to use for logging: ``(message, level) => {...}`` - * ``logLevel`` - |source logLevel|_ (optional): messages with this level will be logged with ``log`` - * ``logLog`` - |source logLogInterface|_ (optional): container for collecting log messages - * ``logLogLevel`` - |source logLevel|_ (optional): messages with this level will be pushed to ``logLog`` - -------- -Returns -------- - -``SignerInternal`` instance - -------- -Example -------- - -.. code-block:: typescript - - const signer = new SignerInternal({ - accountStore, - config, - contractLoader, - web3 - }); - ------------------------------------------------------------------------------- - -.. _signer_getPrivateKey: - -getPrivateKey -=================== - -.. code-block:: javascript - - signer.getPrivateKey(accountId); - -retrieve private key for given account - ----------- -Parameters ----------- - -#. ``accountId`` - ``string``: eth accountId - -------- -Returns -------- - -``Promise`` resolves to ``string``: private key of given account. - -------- -Example -------- - -.. code-block:: javascript - - const privateKey = await runtime.signer.getPrivateKey('0x00000000000000000000000000000000deadbeef'); - ------------------------------------------------------------------------------- - -.. _signer_ensureHashWithPrefix: - -ensureHashWithPrefix -==================== - -.. code-block:: javascript - - signer.ensureHashWithPrefix(input); - -patch '0x' prefix to input if not already added, also casts numbers to hex string - ----------- -Parameters ----------- - -#. ``input`` - ``string``: input to prefix with '0x' - -------- -Returns -------- - -``string``: patched input. - -------- -Example -------- - -.. code-block:: javascript - - const patchedInput = runtime.signer.ensureHashWithPrefix('00000000000000000000000000000000deadbeef'); - // returns 0x00000000000000000000000000000000deadbeef - ------------------------------------------------------------------------------- - -.. _signer_getGasPricex: - -getGasPrice -=================== - -.. code-block:: javascript - - signer.getGasPrice(); - -get gas price (either from config or from api.eth.web3.eth.gasPrice (gas price median of last blocks) or api.config.eth.gasPrice; unset config value or set it to falsy for median gas price - -------- -Returns -------- - -``string``: hex string with gas price. - -------- -Example -------- - -.. code-block:: javascript - - const gasPrice = await runtime.signer.getGasPrice(); - // returns 0x4A817C800 - ------------------------------------------------------------------------------- - -.. _signer_getNonce: - -getNonce -=================== - -.. code-block:: javascript - - signer.getNonce(accountId); - -gets nonce for current user, looks into actions submitted by current user in current block for this as well - ----------- -Parameters ----------- - -#. ``accountId`` - ``string``: Ethereum account ID - -------- -Returns -------- - -``number``: nonce of given user. - -------- -Example -------- - -.. code-block:: javascript - - const patchedInput = runtime.signer.getNonce('00000000000000000000000000000000deadbeef'); - // returns 10 - ------------------------------------------------------------------------------- - -.. _signer_signAndExecuteSend: - -signAndExecuteSend -=================== - -.. code-block:: javascript - - signer.signAndExecuteSend(options, handleTxResult); - -signs the transaction from `executor.executeSend `_ and publishes to the network - ----------- -Parameters ----------- - -#. ``options`` - ``any``: - * ``from`` - ``string``: The address the call "transaction" should be made from. - * ``to`` - ``string``: The address where the eve's should be send to. - * ``value`` - ``number``: Amount to send in Wei -#. ``handleTxResult`` - ``function(error, receipt)``: callback when transaction receipt is available or error - -------- -Example -------- - -.. code-block:: javascript - - const patchedInput = runtime.signer.signAndExecuteSend({ - from: '0x...', // send from this account - to: '0x...', // receiving account - value: web3.utils.toWei('1'), // amount to send in Wei - }, (err, receipt) => { - console.dir(arguments); - }); - ------------------------------------------------------------------------------- - -.. _signer_signAndExecuteTransaction: - -signAndExecuteTransaction -========================= - -.. code-block:: javascript - - signer.signAndExecuteTransaction(contract, functionName, functionArguments, options, handleTxResult); - -signs the transaction from `executor.executeContractTransaction `_ and publishes to the network - ----------- -Parameters ----------- - -#. ``contract`` - ``any``: contract instance from api.eth.loadContract(...) -#. ``functionName`` - ``string``: function name -#. ``functionArguments`` - ``any[]``: arguments for contract creation, pass empty Array if no arguments -#. ``options`` - ``any``: - * ``from`` - ``string``: The address the call "transaction" should be made from. - * ``gas`` - ``number``: Amount of gas to attach to the transaction - * ``to`` - ``string`` (optional): The address where the eve's should be send to. - * ``value`` - ``number`` (optional): Amount to send in Wei -#. ``handleTxResult`` - ``function(error, receipt)``: callback when transaction receipt is available or error - - ------------------------------------------------------------------------------- - -.. _signer_createContract: - -createContract -=================== - -.. code-block:: javascript - - signer.createContract(contractName, functionArguments, options); - -signs the transaction from `executor.createContract `_ and publishes to the network - ----------- -Parameters ----------- - -#. ``contractName`` - ``any``: contractName from contractLoader -#. ``functionArguments`` - ``any[]``: arguments for contract creation, pass empty Array if no arguments -#. ``options`` - ``any``: - * ``from`` - ``string``: The address the call "transaction" should be made from. - * ``gas`` - ``number``: Amount of gas to attach to the transaction - -------- -Returns -------- - -``Promise`` resolves to ``void``: resolved when done. - - -.. required for building markup - - -.. |source contractLoader| replace:: ``ContractLoader`` -.. _source contractLoader: /contracts/contract-loader - -.. |source keyStoreinterface| replace:: ``KeyStoreInterface`` -.. _source keyStoreinterface: /blockchain/account-store.html - -.. |source logLevel| replace:: ``LogLevel`` -.. _source logLevel: /common/logger.html#loglevel - -.. |source logLogInterface| replace:: ``LogLogInterface`` -.. _source logLogInterface: /common/logger.html#logloginterface - -.. |source web3| replace:: ``Web3`` -.. _source web3: https://github.com/ethereum/web3.js/ \ No newline at end of file diff --git a/docs/blockchain/wallet.rst b/docs/blockchain/wallet.rst new file mode 100644 index 00000000..51a96c0a --- /dev/null +++ b/docs/blockchain/wallet.rst @@ -0,0 +1,377 @@ +================================================================================ +Wallet +================================================================================ + +.. list-table:: + :widths: auto + :stub-columns: 1 + + * - Class Name + - Wallet + * - Implements + - `Logger `__ + * - Extends + - `Logger <../common/logger.html>`_ + * - Source + - `wallet.ts `_ + * - Examples + - `wallet.spec.ts `_ + +The ``Wallet`` module is a wrapper for the `MultiSigWallet `_ and allows to create wallets, manage owners and execte transactions with it. +The current api implementations allows only to set a required confirmation count of 1. This basically makes the wallets a multiowned account, where all parties are able to perform transactions on their own. + +The ``Wallet`` module is bound to a wallet contract instance. This instace can either be loaded, which requires an existing `MultiSigWallet `_ contract and a user, that is able to work with it: + +.. code-block:: typescript + + wallet.load('0x0123456789012345678901234567890123456789'); + +If no wallet exists, a new wallet can be created with: + +.. code-block:: typescript + + // account id, that creates the wallet + const accountId = '0x0000000000000000000000000000000000000001'; + // account, that will be able to manage the new wallet + const manager = '0x0000000000000000000000000000000000000001'; + // wallet owners + const owners = [ + '0x0000000000000000000000000000000000000001', + '0x0000000000000000000000000000000000000002', + ]; + await wallet.create(accountId, manager, owners); + +The last example creates a wallet + +- with the account ``0x0000000000000000000000000000000000000001`` (used as ``accountId``) +- that can be managed (adding/removing owners) by ``0x0000000000000000000000000000000000000001`` (used as ``manager``) +- that allows the accounts ``0x0000000000000000000000000000000000000001`` and ``0x0000000000000000000000000000000000000002`` to perform transactions (used as ``owners``) + +Creating wallets via the ``Wallet`` module loads them to the module as well, so there is no need to call the ``load`` function after that. + +So now we have a valid and working wallet loaded to our module and start performing calls. Let's say, we have an instance of an owned contract and want to transfer its ownership, we can do: + +.. code-block:: typescript + + const accountId = '0x0000000000000000000000000000000000000001'; + const newOwner = '0x0000000000000000000000000000000000000002'; + await wallet.submitTransaction(ownedContract, 'transferOwnership', { from: accountId, }, newOwner); + +Looks pretty simple, but comes with a few things to consider: + +- ``accountId`` is the account, that performs the transaction from the "outside perspective" (if you look into a chain explorer like the `evan.network Test-Explorer `_ you'll see, that account ``accountId`` is actually performing the transaction and not the wallet contract) +- ``accountId`` pays the gas cost for the transaction (obviously, when considering the last point) +- from the perspective of the target contract ``ownedContract``, the wallet contract (either loaded or created beforehand) is performing the transaction +- taken our example transaction ``transferOwnership``, **the wallet contract has to be the current owner** and not the account ``accountId`` + +.. figure:: ../_static/wallet_tx_transparent.png + :align: center + :alt: transaction flow in wallet based transactions + + transaction flow in wallet based transactions + +An implementation of an |source executor|_ module, that uses a wallet for contract execution, has been created as |source executorWallet|_. Because the profiles are (externally owned) account based and many modules rely on profiles for data encryption and decryption, the |source executorWallet|_ module should be used with care, when dealing with operations, that require en- or decryption. + + + +-------------------------------------------------------------------------------- + +.. _wallet_constructor: + +constructor +================================================================================ + +.. code-block:: typescript + + new Wallet(options); + +Creates a new Wallet instance. + +---------- +Parameters +---------- + +#. ``options`` - ``WalletOptions``: options for Wallet constructor. + * ``contractLoader`` - |source contractLoader|_: |source contractLoader|_ instance + * ``description`` - |source description|_: |source description|_ instance + * ``eventHub`` - |source eventHub|_: |source eventHub|_ instance + * ``executor`` - |source executor|_: |source executor|_ instance + * ``nameResolver`` - |source nameResolver|_: |source nameResolver|_ instance + +------- +Returns +------- + +``Wallet`` instance + +------- +Example +------- + +.. code-block:: typescript + + const wallet = new Wallet({ + contractLoader, + description, + eventHub, + executor, + nameResolver, + }); + + + +-------------------------------------------------------------------------------- + += Contract Management = +======================= + + +.. _wallet_create: + +create +================================================================================ + +.. code-block:: typescript + + wallet.create(accountId, manager, owners); + +Create a new wallet contract and uses it as its wallet contract. + +---------- +Parameters +---------- + +#. ``accountId`` - ``string``: account id, that creates the wallet +#. ``manager`` - ``string``: account, that will be able to manage the new wallet +#. ``owners`` - ``string[]``: wallet owners + +------- +Returns +------- + +``Promise`` returns ``void``: resolved when done + +------- +Example +------- + +.. code-block:: typescript + + await wallet.create(accounts[0], accounts[0], [accounts[0]]); + + + +-------------------------------------------------------------------------------- + +.. _wallet_load: + +load +================================================================================ + +.. code-block:: typescript + + wallet.load(contractId); + +Load wallet contract from address and uses it as its wallet contract. + +---------- +Parameters +---------- + +#. ``contractid`` - ``string``: a wallet contract address + +------- +Returns +------- + +``Promise`` returns ``void``: resolved when done + +------- +Example +------- + +.. code-block:: typescript + + wallet.load('0x0123456789012345678901234567890123456789'); + + + +-------------------------------------------------------------------------------- + += Transactions = +====================== + +.. _wallet_submitTransaction: + +submitTransaction +================================================================================ + +.. code-block:: typescript + + wallet.submitTransaction(target, functionName, inputOptions[, ...functionArguments]); + +Submit a transaction to a wallet, as required is fixed to 1, this will immediately execute the transaction. + +---------- +Parameters +---------- + +#. ``target`` - ``any``: contract of the submitted transaction +#. ``functionName`` - ``string``: name of the contract function to call +#. ``inputOptions`` - ``any``: currently supported: from, gas, event, getEventResult, eventTimeout, estimate, force +#. ``functionArguments`` - ``any[]``: optional arguments to pass to contract transaction + +------- +Returns +------- + +``Promise`` returns ``any``: status information about transaction + +------- +Example +------- + +.. code-block:: typescript + + await wallet.submitTransaction(testContract, 'transferOwnership', { from: accounts[0], }, accounts[1]); + + + +-------------------------------------------------------------------------------- + += Account Management = +====================== + +.. _wallet_addOwner: + +addOwner +================================================================================ + +.. code-block:: typescript + + wallet.addOwner(accountId, toAdd); + +Function description + +---------- +Parameters +---------- + +#. ``accountId`` - ``string``: account with management permissions on wallet +#. ``toAdd`` - ``string``: account to add as an owner + +------- +Returns +------- + +``Promise`` returns ``void``: resolved when done + +------- +Example +------- + +.. code-block:: typescript + + await wallet.addOwner(accounts[0], accounts[1]); + + + +-------------------------------------------------------------------------------- + +.. _wallet_removeOwner: + +removeOwner +================================================================================ + +.. code-block:: typescript + + initializedModule.removeOwner(arguments); + +Remove an owner from a wallet contract. + +---------- +Parameters +---------- + +#. ``accountId`` - ``string``: account with management permissions on wallet +#. ``toAdd`` - ``string``: account to remove from wallet owners + +------- +Returns +------- + +``Promise`` returns ``void``: resolved when done + +------- +Example +------- + +.. code-block:: typescript + + await wallet.removeOwner(accounts[0], accounts[1]); + + + + + +-------------------------------------------------------------------------------- + +.. _wallet_getOwners: + +getOwners +================================================================================ + +.. code-block:: typescript + + wallet.getOwners(); + +Get all owners of a wallet. + +---------- +Parameters +---------- + +(none) + +------- +Returns +------- + +``Promise`` returns ``string[]``: array of account ids + +------- +Example +------- + +.. code-block:: typescript + + console.dir(await wallet.getOwners()) + // Output: + // [ '0x0123456789012345678901234567890123456789' ] + + + +.. required for building markup +.. |source contractLoader| replace:: ``ContractLoader`` +.. _source contractLoader: /contracts/contract-loader.html + +.. |source description| replace:: ``Description`` +.. _source description: /blockchain/description.html + +.. |source eventHub| replace:: ``EventHub`` +.. _source eventHub: /blockchain/event-hub.html + +.. |source executor| replace:: ``Executor`` +.. _source executor: /blockchain/executor.html + +.. |source executorWallet| replace:: ``ExecutorWallet`` +.. _source executorWallet: /blockchain/executor-wallet.html + +.. |source logLevel| replace:: ``LogLevel`` +.. _source logLevel: /common/logger.html#loglevel + +.. |source logLogInterface| replace:: ``LogLogInterface`` +.. _source logLogInterface: /common/logger.html#logloginterface + +.. |source nameResolver| replace:: ``NameResolver`` +.. _source nameResolver: /blockchain/name-resolver.html diff --git a/docs/common/logger.rst b/docs/common/logger.rst deleted file mode 100644 index 66f9cdb7..00000000 --- a/docs/common/logger.rst +++ /dev/null @@ -1,187 +0,0 @@ -================================================================================ -Logger -================================================================================ - -.. list-table:: - :widths: auto - :stub-columns: 1 - - * - Class Name - - Logger - * - Source - - `logger.ts `_ - -The `Logger `_ class is used throughout the package for logging events, updates and errors. Logs can be written by classes, that inherit from the `Logger `_ class, by using the `this.log` function. A log level can be set by its second parameter: - -.. code-block:: javascript - - this.log('hello log', 'debug'); - - All log messages without a level default to level 'info'. If not configured otherwise, the following behavior is used: - -- drop all log messages but errors -- log errors to console.error - -It can be useful for analyzing issues to increase the log level. You can do this in two ways: - -- Set the environment variable `DBCP_LOGLEVEL` to a level matching your needs, which increases the log level for all modules and works with the default runtime. For example: - -.. code-block:: sh - - export DBCP_LOGLEVEL=info - - -- When creating a custom runtime, set the `logLevel` property to a value matching your needs, when creating any module instance. This allows you to change log level for single modules, but requires you to create a custom runtime, e.g.: - -.. code-block:: javascript - - const { ContractLoader } = require('@evan.network/dbcp'); - const Web3 = require('web3'); - - // web3 instance for ContractLoader - const web3 = new Web3(); - web3.setProvider(new web3.providers.WebsocketProvider('...')); - - // custom log level 'info' - const contractLoader = new ContractLoader({ web3, logLevel: 'info', }); - -All loggers can have a custom LogLog storage where all logmessages with a given level will be stored. You can access the storage for the current logger module at the property ``logLog``. All messages are stored with the following markup: - -.. code-block:: javascript - - { - timestamp, // current date in millis - level, // loglevel of the message - message // log message - } - -You can configure the current LogLogLevel at the property ``logLogLevel`` at instantiation of your module. - ------------------------------------------------------------------------------- - -.. _logger_constructor: - -constructor -================================================================================ - -.. code-block:: typescript - - new Logger(options); - -Creates a new Logger instance. - ----------- -Parameters ----------- - -#. ``options`` - ``LoggerOptions``: options for Logger constructor. - * ``log`` - ``Function`` (optional): function to use for logging: ``(message, level) => {...}`` - * ``logLevel`` - |source logLevel|_ (optional): messages with this level will be logged with ``log`` - * ``logLog`` - |source logLogInterface|_ (optional): container for collecting log messages - * ``logLogLevel`` - |source logLevel|_ (optional): messages with this level will be pushed to ``logLog`` - -------- -Returns -------- - -``Logger`` instance - -------- -Example -------- - -.. code-block:: typescript - - const logger = new Logger(); - - - --------------------------------------------------------------------------------- - -.. _logger_log: - -log -=================== - -.. code-block:: javascript - - logger.log(message, level); - -log message with given level - - - ----------- -Parameters ----------- - -#. ``message`` - ``string``: log message -#. ``level`` - ``string``: log level as string, defaults to 'info' - -------- -Example -------- - -.. code-block:: javascript - - runtime.executor.log('test', 'error'); - ------------------------------------------------------------------------------- - -= Additional Components = -========================= - ------------ -Interfaces ------------ - - - -.. _logger_logLogInterface: - - -LogLogInterface -^^^^^^^^^^^^^^^ - -A different LogLog storage can be attached to the logger instance of the module. The storage must implement the following functions (default array like instance) - -.. code-block:: typescript - - export interface LogLogInterface { - push: Function; - map: Function; - filter: Function; - }; - ------ -Enums ------ - -.. _logger_LogLevel: - -LogLevel -^^^^^^^^^^^^^ - -Available LogLevels for the logger instance, free definable between error and gasLog - -.. code-block:: typescript - - export enum LogLevel { - debug, - info, - notice, - warning, - error, - - gasLog = 100, - disabled = 999, - }; - - -.. required for building markup - -.. |source logLevel| replace:: ``LogLevel`` -.. _source logLevel: /common/logger.html#loglevel - -.. |source logLogInterface| replace:: ``LogLogInterface`` -.. _source logLogInterface: /common/logger.html#logloginterface \ No newline at end of file diff --git a/docs/common/validator.rst b/docs/common/validator.rst deleted file mode 100644 index a49685f5..00000000 --- a/docs/common/validator.rst +++ /dev/null @@ -1,116 +0,0 @@ -================================================================================ -Validator -================================================================================ - -.. list-table:: - :widths: auto - :stub-columns: 1 - - * - Class Name - - Validator - * - Extends - - `Logger `_ - * - Source - - `validator.ts `_ - * - Tests - - `validator.spec.ts `_ - -The Validator module can be used to verfiy given JSON schemas. - ------------------------------------------------------------------------------- - -.. _validator_constructor: - -constructor -================================================================================ - -.. code-block:: typescript - - new Validator(options); - -Creates a new Validator instance. - ----------- -Parameters ----------- - -#. ``options`` - ``ValidatorOptions``: options for Validator constructor. - * ``schema`` - ``any``: the validation schema definition - * ``log`` - ``Function`` (optional): function to use for logging: ``(message, level) => {...}`` - * ``logLevel`` - |source logLevel|_ (optional): messages with this level will be logged with ``log`` - * ``logLog`` - |source logLogInterface|_ (optional): container for collecting log messages - * ``logLogLevel`` - |source logLevel|_ (optional): messages with this level will be pushed to ``logLog`` - -------- -Returns -------- - -``Validator`` instance - -------- -Example -------- - -.. code-block:: typescript - - const nameResolver = new Validator({ - schema - }); - - - --------------------------------------------------------------------------------- - -.. _validator_validate: - -validate -=================== - -.. code-block:: javascript - - validator.validate(data); - -validate a given data object with the instantiated schema - - - ----------- -Parameters ----------- - -#. ``data`` - ``any``: to be validated data - -------- -Returns -------- - -``bool | strings[]``: true if data is valid, array of object if validation is failed - ------------------------------------------------------------------------------- - -.. _validator_getErrorsAsText: - -getErrorsAsText -=================== - -.. code-block:: javascript - - validator.getErrorsAsText(); - -returns errors as text if previous validation was failed - - -------- -Returns -------- - -``string``: all previous validation errors concatenated as readable string - - -.. required for building markup - -.. |source logLevel| replace:: ``LogLevel`` -.. _source logLevel: /common/logger.html#loglevel - -.. |source logLogInterface| replace:: ``LogLogInterface`` -.. _source logLogInterface: /common/logger.html#logloginterface \ No newline at end of file diff --git a/docs/contracts/base-contract.rst b/docs/contracts/base-contract.rst index 88d9c45c..5d769c74 100644 --- a/docs/contracts/base-contract.rst +++ b/docs/contracts/base-contract.rst @@ -9,10 +9,10 @@ Base Contract * - Class Name - BaseContract * - Extends - - `Logger `_ + - `Logger <../common/logger.html>`_ * - Source - `base-contract.ts `_ - * - Tests + * - Examples - `base-contract.spec.ts `_ The `BaseContract `_ is the base contract class used for diff --git a/docs/contracts/contract-loader.rst b/docs/contracts/contract-loader.rst deleted file mode 100644 index a9b0db8c..00000000 --- a/docs/contracts/contract-loader.rst +++ /dev/null @@ -1,120 +0,0 @@ -================================================================================ -Contract Loader -================================================================================ - -.. list-table:: - :widths: auto - :stub-columns: 1 - - * - Class Name - - ContractLoader - * - Extends - - `Logger `_ - * - Source - - `contract-loader.ts `_ - * - Tests - - `contract-loader.spec.ts `_ - -The `ContractLoader `_ is used when loading contracts without a DBCP description or when creating new contracts via bytecode. In both cases additional information has to be passed to the `ContractLoader `_ constructor. - -Loading contracts requires an abi interface as a JSON string and creating new contracts requires the bytecode as hex string. Compiling Ethereum smart contracts with `solc `_ provides these. - -Abis, that are included by default are: - -- AbstractENS -- Described -- EventHub -- Owned -- PublicResolver - -Bytecode for these contracts is included by default: - -- Described -- Owned - -Following is an example for loading a contract with a custom abi. The contract is a `Greeter Contract `_ and a shortened interface containing only the `greet` function is used here. - -They can be side-loaded into an existing contract loader instance, e.g. into a runtime: - -.. code-block:: javascript - - runtime.contractLoader.contracts['Greeter'] = { - "interface": "[{\"constant\":true,\"inputs\":[],\"name\":\"greet\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]", - }; - - -.. _contract_loader_getCompiledContractn: - -getCompiledContract -=================== - -.. code-block:: javascript - - contractLoader.getCompiledContract(name); - -gets contract from a solc compilation - ----------- -Parameters ----------- - -#. ``name`` - ``string``: Contract name - -------- -Returns -------- - -``any``: The compiled contract. - -------- -Example -------- - -.. code-block:: javascript - - const address = '0x9c0Aaa728Daa085Dfe85D3C72eE1c1AdF425be49'; - const accountId = '0x000000000000000000000000000000000000beef'; - const description = await runtime.description.getDescription(address, accountId); - console.dir(description); - // Output: - // { public: - // { name: 'DBCP sample greeter', - // description: 'smart contract with a greeting message and a data property', - // author: 'dbcp test', - // tags: [ 'example', 'greeter' ], - // version: '0.1.0', - // abis: { own: [Array] } } } - ------------------------------------------------------------------------------- - -.. _contract_loader_loadContract: - -loadContract -=================== - -.. code-block:: javascript - - contractLoader.loadContract(name, address); - -creates a contract instance that handles a smart contract at a given address - ----------- -Parameters ----------- - -#. ``name`` - ``string``: Contract name -#. ``address`` - ``string``: Contract address - -------- -Returns -------- - -``any``: contract instance. - -------- -Example -------- - -.. code-block:: javascript - - const greeter = runtime.contractLoader.loadContract('Greeter', '0x9c0Aaa728Daa085Dfe85D3C72eE1c1AdF425be49'); diff --git a/docs/contracts/data-contract.rst b/docs/contracts/data-contract.rst index ce23b257..68b86c8b 100644 --- a/docs/contracts/data-contract.rst +++ b/docs/contracts/data-contract.rst @@ -9,10 +9,10 @@ Data Contract * - Class Name - DataContract * - Extends - - `BaseContract `_ + - `BaseContract <../contracts/base-contract.html>`_ * - Source - `data-contract.ts `_ - * - Tests + * - Examples - `data-contract.spec.ts `_ The `DataContract `_ is a secured data storage contract for single properties and lists. If created on its own, DataContracts cannot do very much. They rely on their authority to check which entries or lists can be used. @@ -125,7 +125,7 @@ Now create a contract with: const contract = await dc.create(factoryName, accounts[0], businessCenterDomain); -Okay, that does not provide a description for the contract. Let's add a description to the process. The definition is a `DBCP `_ contract definition and is stored in an ``Envelope`` (see :doc:`Encryption `): +Okay, that does not provide a description for the contract. Let's add a description to the process. The definition is a `DBCP `_ contract definition and is stored in an ``Envelope`` (see :doc:`Encryption <../encryption/index>`): .. code-block:: typescript @@ -134,7 +134,7 @@ Okay, that does not provide a description for the contract. Let's add a descript "name": "Data Contract Sample", "description": "reiterance oxynitrate sat alternize acurative", "version": "0.1.0", - "author": "contractus", + "author": "evan GmbH", "dataSchema": { "list_settable_by_member": { "$id": "list_settable_by_member_schema", diff --git a/docs/contracts/rights-and-roles.rst b/docs/contracts/rights-and-roles.rst index a78ccec2..d9331600 100644 --- a/docs/contracts/rights-and-roles.rst +++ b/docs/contracts/rights-and-roles.rst @@ -9,10 +9,10 @@ Rights and Roles * - Class Name - RightsAndRoles * - Extends - - `Logger `_ + - `Logger <../common/logger.html>`_ * - Source - `rights-and-roles.ts `_ - * - Tests + * - Examples - `rights-and-roles.spec.ts `_ The `RightsAndRoles `_ module follows the approach described in the evan.network wik at: @@ -374,26 +374,6 @@ Example -.. required for building markup -.. |source contractLoader| replace:: ``ContractLoader`` -.. _source contractLoader: /contracts/contract-loader.html - -.. |source executor| replace:: ``Executor`` -.. _source executor: /blockchain/executor.html - -.. |source logLevel| replace:: ``LogLevel`` -.. _source logLevel: /common/logger.html#loglevel - -.. |source logLogInterface| replace:: ``LogLogInterface`` -.. _source logLogInterface: /common/logger.html#logloginterface - -.. |source nameResolver| replace:: ``NameResolver`` -.. _source nameResolver: /blockchain/name-resolver.html - -.. |source web3| replace:: ``Web3`` -.. _source web3: https://github.com/ethereum/web3.js/ - - -------------------------------------------------------------------------------- .. _rights-and-roles_transferOwnership: @@ -433,4 +413,25 @@ Example contract, // contract to be updated contractOwner, // current owner newOwner, // this account becomes new owner - ); \ No newline at end of file + ); + + + +.. required for building markup +.. |source contractLoader| replace:: ``ContractLoader`` +.. _source contractLoader: /contracts/contract-loader.html + +.. |source executor| replace:: ``Executor`` +.. _source executor: /blockchain/executor.html + +.. |source logLevel| replace:: ``LogLevel`` +.. _source logLevel: /common/logger.html#loglevel + +.. |source logLogInterface| replace:: ``LogLogInterface`` +.. _source logLogInterface: /common/logger.html#logloginterface + +.. |source nameResolver| replace:: ``NameResolver`` +.. _source nameResolver: /blockchain/name-resolver.html + +.. |source web3| replace:: ``Web3`` +.. _source web3: https://github.com/ethereum/web3.js/ \ No newline at end of file diff --git a/docs/contracts/service-contract.rst b/docs/contracts/service-contract.rst index 84b2c548..6cac8b1e 100644 --- a/docs/contracts/service-contract.rst +++ b/docs/contracts/service-contract.rst @@ -9,10 +9,10 @@ Service Contract * - Class Name - ServiceContract * - Extends - - `Logger `_ + - `Logger <../common/logger.html>`_ * - Source - `service-contract.ts `_ - * - Tests + * - Examples - `service-contract.spec.ts `_ @@ -129,7 +129,7 @@ setService .. code-block:: typescript - serviceContract.setService(contract, accountId, service, businessCenterDomain); + serviceContract.setService(contract, accountId, service, businessCenterDomain[, skipValidation]); Set service description. @@ -141,6 +141,7 @@ Parameters #. ``accountId`` - ``string``: Ethereum account ID #. ``service`` - ``any``: service to set #. ``businessCenterDomain`` - ``string``: domain of the business the service contract belongs to +#. ``skipValidation`` - ``bool`` (optional): skip validation of service definition, validation is enabled by default ------- Returns @@ -364,6 +365,44 @@ Example +-------------------------------------------------------------------------------- + +.. _service-contract_getCallOwner: + +getCallOwner +================================================================================ + +.. code-block:: typescript + + serviceContract.getCallOwner(contract, callId); + +Gets the owner/creator of a call. + +---------- +Parameters +---------- + +#. ``contract`` - ``any|string``: smart contract instance or contract ID +#. ``callId`` - ``number``: index of the call to retrieve owner for + +------- +Returns +------- + +``Promise`` returns ``string``: account id of call owner + +------- +Example +------- + +.. code-block:: typescript + + console.log(await serviceContract.getCallOwner(contract, 2)); + // Output: + 0x0000000000000000000000000000000000000001 + + + -------------------------------------------------------------------------------- .. _servicecontract_addToCallSharing: diff --git a/docs/contracts/sharing.rst b/docs/contracts/sharing.rst index 0dddbcea..5bdb9459 100644 --- a/docs/contracts/sharing.rst +++ b/docs/contracts/sharing.rst @@ -9,10 +9,10 @@ Sharing * - Class Name - Sharing * - Extends - - `Logger `_ + - `Logger <../common/logger.html>`_ * - Source - `sharing.ts `_ - * - Tests + * - Examples - `sharing.spec.ts `_ For getting a better understanding about how Sharings and Multikeys work, have a look at `Security `_ in the evan.network wiki. diff --git a/docs/dbcp.json b/docs/dbcp.json new file mode 100644 index 00000000..b4140e7b --- /dev/null +++ b/docs/dbcp.json @@ -0,0 +1,38 @@ +{ + "public": { + "author": "evan GmbH", + "dapp": { + "dependencies": {}, + "entrypoint": "index.html", + "files": [ + "index.html" + ], + "origin": "QmT4jiqXcN4gJQf7g6NhuSVUKHLD9kCRW3b8uD4wGP2o2Z", + "primaryColor": "#1a68b7", + "secondaryColor": "#eaeaea", + "type": "library" + }, + "description": "blockchain-core documentation", + "i18n": { + "description": { + "de": "API Dokumentation", + "en": "API documentation" + }, + "name": { + "de": "Blockchain-Core Dokumentation", + "en": "blockchain-core documentation" + } + }, + "imgSquare": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAABmJLR0QA/wAAACLmRz0XAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4ggKDS42BPC0agAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAABgfSURBVHja7Z19kFTVmcZ/fbsHZgZsxgEJwoiFAUMka1wTXfBrjVgJgkmMAmoq2VLLj8SoCabWrSWpxKRittaqgFFj/NjSVMXyCzWaBDQp0axfsCRxjSuBIJElIIsI4zAzzAwz0937R5+R0fnq7rnn9j3nPr+q+YfquUy/532fe89zzzlvavryTQinyQJHA03AVGAKMBmYBDQCDeYz44F6oBYYA2SAwFwjD/QC3UAX0AG0A61AC9AM7AX2ALuBXcBOYLv5jHCUjELgBAHwMeA4YDZwLDATOAaYGNL1x5if8WX+7j7gTWArsAXYDPwZeN0Ii5AAiDJIAycDnwROBE4Aju93t44bE83PSR/49zzwGvAq8ArwB2ADkNMQx4eUpgBVpwE4AzgNOAWYa0TAR3LAeuBl4EXgeTPFEBKARPEp4GzgLFPwSWY98CzwDPCcUkMC4CONwLnAQmABMEEhGZT9wNPAGuDXFM1HIQ/ASY4AzgfOM0UvRmYCcKH5wYjBE8DjwDsKj54AXBDUi4ClwGcVjlD5FfAI8BDFV5YiBAKFIBROB+4C3gV+ruK3wmdNbN81sT5dIZEAVJN64BqKr7eeB66k/HfoonzGm1g/b2J/jRkLIQGIhDnAj82c9DbgEwpJ1fiEGYN3zJjMUUgkALaYDzxGcYXbdbrrxO5p7DozNo+ZsRISgFA4j0Pvqc9XOGLP+WasnjVjJyQAFXEB8BLwC4oLd4RbfMqM3UtmLIUEoCTOpWgwPUpxaa5wm1PMWD5vxlZIAAblVGA1xffNesXkH6ebsV1txlpIAACYAdxHcXPKQoXDexaasb7PjL0EIMF8B/grcInqInFcYsb+OxKA5HEBsAn4HpBSLSSWlMmBTSTUKEyaABwNPEDRFJqt/BeG2SYnHjA5IgHwkGuM0l+sfBdDcLHJkWskAP7wEYrO721AnXJcjECdyZXVJnckAA7zNeB/kLsvymehyZ2vSQDcYzLFveO3AzXKZVEhNSaHHjE5JQFwgM8D/w0sUf6KkFhicurzEoB4cxPFI6SmKmdFyEw1uXWTBCCeg7MGWK48FZZZbnJtqgQgHnwa+C/gHOWmiIhzTM59WgJQXa4FfkOxL54QUdJkcu9aCUB1uAW4VXkoqsytJhclABFRT9GM+bpyT8SEr5ucrJcA2OXDwH/i4esY4TyfN7n5YQmAHeYBv6PYNVeIOPJJk6PzJADhshBYi8w+EX+aTK4ulACEw0UUN2ZoI49whTqTsxdJAEbHpcCDyifhKA+aHJYAVMBVwL3KIeE495pclgCUwVeBO5U7whPuNDktASiBK4E7lDPCM+4wuS0BGIZLKLZ+FsJH7iJmJ1DHSQCWUDyrXQifuY8YnVURFwH4DMVTV4RIAo+YnJcAACcBq5QTImGsMrmfaAE4GngYOEz5IBLGYSb3j06qAGQoLpSYoVwQCWWGqYFMEgXgARzaNCGEJeaZWkiUAPw7OrVXiD6WmJpIhABcAdygMRfifdxgasNrATgduFtjLcSg3G1qxEsBOBxt7hFiJO41teKdANwDzNT4CjEsM02teCUAy4ELNLZClMQFRNTkJgoBOBvP2ikJEQE3mdqxiu0FCPVoay8Axx1ZS7Z2oN7++f8O0tqVC+16o7120+E1NDXUhH5dgGxtmuOOHFvy53e29LDz3Z4kp80dwAlAh6sCcDswS+UP3100mbkzBh4bv+TWV9nQVRva9fpz4d1vsn57eYW65MQJfOOsScNf957/Zf22HkiV9wB53JFjefjy6SV//pZn97Jy7d4kp80sU0OXuTgF+Cdifh5aHCjkuskfsJPk+Y5m8l2t4V+3q5XcAfuFme/ugEI+6SlyqaklpwRgKrBS5V1ioh9sp3CwPXxxKeTJdzRTyHWHe93eLgrdHRS6O+wGJtcdidA4wEosdSO2JQA/Aho1bmXkuoVCfU9g2vZYuZPmDuy1focudHeQ72xJeno0mppyQgC+jAPnocdvLpAn326noAr5Xjt30kKeXPse+09InS32nzbiz0WmtmItAA3AzarmUfgBHc3W7qRWphk9XVZ8hsGeNmw9ITnEzabGYisA/wZMUSnHzw+wOc3Id7ZAvtfZJySHmGJqLJYCMB/4iko4xnc7W0VUyEdi1hVkCmJqbH4cBeAHKt0Q76qWjLtCrtuKqRbVVKDQ3WFtmuQQP4ibAFwLzFXZhnlT7bV2t8t3tVox1fIW32QM+PstTZMcYa6puVgIwATgRpWspbudpbtq7sBeK/P2fHs0j+i5iMQmxtxoaq/qAvAd9M7f3t3OVqIX8uTawn+FZ2uKMaifYWma5AiNpvaqKgAfBa5XmVq+27XutucHWJhP5ztbIrk7F/K9kaxDiDHXmxqsmgAsV3lGYghYS/R8VyuF3q7wrxvR3bnQ05V0U3B5tQRgHvAlVWdEGtDTZe3ROmehWAv53siW8CbcFPwSozhefzQCoJN9o/YDOlus3K1tPWHYeroYVMSSbQreELUAnAmcp5Ksgh9ga32ApSeMyFbvFfLWvBIHOM/UZGQCsEylWEU/oHW3xSeMkLcOW1zPEGVsHGBZVAJwGvA5VWIVNSDXTaHHzqN1oSf8BUKRnB3QLzb5ZC4X/pypzbKo5Eiw65JaeKWcwzcU2dr0oP8+pylb2fXqa0b8TCXXbmqss3LdVCrPcUfWlv23zDu2siUmu7pyvNWeTlqKXge8WNa4TF++qZzPHw/8KakC8PDl00c8h0/EgxWrt3LLCx2k0mOS9tU/DrxmawpwtVJLuEJCTcGyarQcAfgQcJXSSjhDMk3Bq0ythi4AVyijhHMakExT8AobAnC50km4SP5geyRnFcSIy8MWgAuBo5VKwlkR6GiObFViDDja1GxoAnCJUki4Tq5tj/2zC+NDSTVbyjqA2cACpc/IrFi9VUGIiKbGOpbOm1amIVA8AyGdnVJ2WzMHWWBqd/NoBUA7/krkR7+WAETFvGMbyxcADp2BEIyblIQwfQn49minAF9Uugmv/IDkmIIj1u5IAvBpYIZSRngnAskwBWeYGq5YAC5UqghfybXtScIZAheORgAWK02EtySj29DiSgXgC0BWWSK81gD/uw1lTS0PSmYEARAhMacpS7Y+Y/3/2bijjdbOnmE/U+kW26jZua+THfs6K/rdcrcSB7WQqhl+p+f6bc52KP4C8ItyBcDZQz+Wzbfziqepoabi3/3ektmRFN7ilRtYt2X4U3IfXXayE+O4YvXWil+tLp03raLXhMMx/Z9fITXGye3gnyv3CeAcQug6Ui2+cVYi3vGKiMkd2EsmMxWCjGt/+gRT00+V6gEs1HAL8UHDIG/tUNYIGLSmhxIALf0VYjANsNRNKQIWlCoAHwNmaqiFGJz8wXYXG5HMNLU9ogdwtoZYuM6OfZ3srPANQkl+QEcz6cwY184cPBt4fSQBmO/64K9Y86aVedqSudM4amKdqssBVq1/y+7mLNOdOD1hqks7C+cDt4wkAGe6Pvgr1+61Mk+bN6tRAiD6aUCx6Ul6/GRX/uQzR/IATgHGuz4wQW2WVE2tMlTYF4HuDpd2Fo43NT6kAJzmy8Ckx01KwqEPIgY4trPwtOEE4FRvRiXIENQ1KDtFJDi0PuDU4QRgrk+DoqmAiNAQsNJi3QJzhxKAY4HJvo2LpgIiMg2w1GI9ZCabWh8gACd5OSqaCogo/YDOlsg6IY+CkwYTgBN9HZSgNpvEJpGiWn7Agb1xP378xMEE4ASfByUYrx2CIkI/oC3WfsAJgwnAx30ek1R6jKYCIjoNiHdPwo9/UACOAib6PihBXYOmAiI6PyC+m4Ymmpp/TwDmJGVQNBUQkfoBHc1xPXl4DhzaCzA7KQPSNxVw4HWNNUY6Miwu7BjFbr5yzwS0Fjdz8nAM25HNBp7uE4CP+JTgI58JOKkiAWjyZCPQ4pUbvBc5G2cCTvvq0xX7ATHcNPSR/k8As3wa/NLOBNRUQERH36ahoDY2J+3P6u8BHKMhEsIu+Xj5Acf0CUCA+v8JEQm51t1x2TQ0AwgCYLqGRYio5gKx2jQ0PcC8DxRCRKQB8dk0dFQGmKYhSRaudAZ6ZP1bPLLuLT/9gM4WUjW1pDJV3a4+LQNMUUkkC1d6A657o9nrcci17SEzoaqdhqZkgA+pJIRv2D4WPDQ/oO9k4erwoQxwhG+Dv2K1neOgdSy4O1g/FjwsDTCdhoL6qjyVHZHBw01AK9futWKy6FhwYcUP6GollR5DamzkB3JPDIDDfQtoUJsl5V4HV5FgqrRp6PAAyHoXzVSgXX/CLcymoYgXCWUD4DAf45nK1JIaU6/EEu5oQPSdhw8LgHG+BjRd36gTgYVbfsDB9ig7DY0LAH9drSATp91XQpQmAtH5AXUBMNbnYAZ1DTIEhXsiEE2nobEBUON7MGUICuf8gHxvFJuGagIg7XswU5lagrHjlVXCLRGwv2koHQCpJAQzkCEoXJwKdLbY7DycCoBCIiKZCtQXQDiJxc7DhQDIJSWQahEmHDUEiicJWdCWDNDDocNBvWDujGEWAOWmk6twsUW2vkbJ6AjXL5rJ9YtmhnrNSk8FDkUD7Gwa6skAB/FsLcDDl+uUM+GhH9DVGvYK14MB0KnQCuGIH3Bgb5iLhDoD4IDCKoQ7fkCIm4YOBECboiqEQxoQ3qahtgBoVUiFcMwPCKfzcGsAvKtwCpFIP+DdANinUArh6JPA6BYJ7QuAdxRGIRz1A/K95A7srfTX38kAb/sWlDieCvzdVZvJ1ttfb7Vxhzzdvhxw4VTgUESgu4N8Z0slS93fzgC7fQvILc+1jEYVh2Q0pwJv3CmvVVicClTWaWh3AHjXeyk1dry2/4rEUcGmobcCYIePwQjGTdLGH5E0Q6DcTUM7AuBvvsYjnZ2iMwBEsjSgvEVCfwuAPLDNy2ikgqIICJEkP6CrlUJ3x0gf2wbk+26Pb/oajFR6TLX6rglRPT/gwF7I9w73kTcB+gTgDZ+DEdRmZQqK5PkBw5uCb/QXgL/4Ho+gvlGmoJAfcIi/9BeAzd5HIxWQPmyyTEGRLD9g6E1Dm/sLwMZERCPIFEVAiCT5AYN3GtrYXwB2kJBNQalMrUxBkTg/4AObhvaZmqf/8/CfkhKPoDarzsEiYRrwvk1D79V6fwF4NUkBSWuloEiaCHR39HUefq/W+29PeyVR0UgFBOMnFZdO2m/CKCJmydxpzJsV7lRv8coNzscl39FMKjPmlb5NQ/0F4Pe+DP72m2aX8enjVS0ectTEuop3bvpOrm3P7zMNTcWbYL9/3wLsUXiE8Jo9FPJb+joPf/Cl+HrFRwivWQ+m83BH8wABeEnxEcJr3qvxfFfrAAF4UfERwmveV+MfFICXgXbFSAgvaTc1PqQAAPxOcRLCSwbU9mACsFZxEsJL1pYiAM8oTkJ4yYDaHuyg+teBrcBMxctPbPVNCJuXtzRrsMJjq6ntEQUA4GngGsXMT5LSMEMMqGlKFYA1zgpAvpd1lu4cc47Kkq3LKJUcecqR0A2o6ZIF4ClgPzDBua8ZZFh65xbynS2hX/rRZScz71idJSCcY7+p6YHlMswv/dLVbxvUNWi/vxAl1PJwAvALl79xetwkUoEe14UYrpZHEgB3O1qmAgKd/ydEa6UCAPCoy99cTUGEGL6GRxKAh13/9jr/TyScYWt4pEnybyn2EJvhuh+Q691FYfhWSaOX2mUnK90iIltfoyCMzDZTwxULAMADwLecDoPxA3L7d1n9b/SKUMSMB0Z8Qi7hIvf7EAn5ASKB3B+GAGxmiGWELvoBahIqEsLTlNDyr9RGeT/zJSpqEioSQkk1W6oAPAxs9yIsph+AmoQKj9lOiW/wyqmC//AlOqn0GNLyA4S/lFyr5QjAPT5FKDV2vPwA4Ssl12o5i+XfBu4CrvLJDyj0dg/WOnlQKmkN9dZPFwz679O+WpmvOtT1RnvtUnY6Ll65oaKt1t88dybXLyr9fJlK/x8BpkbftvEEAHCHV6GSHyD8o6waLTfzXwNWeaUB8gOEP6wyNWpNAABu9S1q8gOEJ5Rdm5UIwIs4fFjIkIEYN0nrA4TL/JIKOntVOvld6WME04dNlh8gXKWimqw0238HPOFdCIMM6XGTlErCNZ6gwo5eo7nd3exjJFNj6glqs0op4RIV1+JoBGAdnuwUHBAU7RcQ7nC/qcXIBQDgh75GVX6AcIRR1eBoM3wTsMLLsMoPEPFnhanBqgkAwPcBL9dtyg8QMabZ1B7VFoD9wI2+RjmobyRVU6t0E3HjRlN7VRcAgNuA9d76AePlB4hYsd7UHHERAIBvexvuVFA0BYWIB6HVWpgCsBa401sNyNQS1DUo9US1udPUWuwEAOBfgd3e+gF1DfIDRDXZbWqMuApAC3CDzyMgP0BUkRtMjcVWAAB+DjwkP0CIUHnI1BZxFwCAb+Lp2gD5AaIKNJuawhUB2AUs83lEgroGNR0VUbHM1FT4N7PpyzfZ/MPvBS71dlgKeXL7h286OtRBm5UeellK/8FKrj2nKUu2fvgzYjfuaKO1s6fsax81sY6miXUlf77S/8dT7gMus/Y0a1kA6oFXgVneakCu23rTUZFY3gBOADqsPcla/gIdwNU+j5CajgqLXG2z+KMQAIBncL29+EhBrM3KDxBh8y1TO7guAFDcs/yYz6OVHjeJVJBR2ooweIyIztqIckXLFcBWf+cCAYHWB4jRs9XUCr4JwLtYdDPlBwhPuMzUincCAPACcKXvfoCajIgKudLUCL4KABQ7l97stQjoUFFRPjdThQ7c1drV8i941mNwgB+gpqOidFaZmiApAgDwRUZxnLELfoCajooSWGdqgaQJQC9wMbDNWxFQ01ExPNtMDfQmUQAAtgMXAm3yA0TCaDO5v72q+RmDQPweWCI/QCSMJSb3SboAAPwGWCo/QCSEpSbnkQAcYhUebx2WHyAMlxKjN2Bxey79GXCVt37AuEnyA5LNVSbHkQAMzd14vIVYTUcTy9Umt5EAjMxPga/4+RigpqMJ5Csmp5EAlM5deLp5SE1HE8VlJpeRAJTPfRQXSvj3IKD1AUngYpPDSAAq5yFgEdApP0A4QqfJ2dj3x3Al+9YA84Gd8gNEzNlpcnWNEynoUGDXAWcCf5AfIGLKH0yOOrPJzbXnz78C/wg86Z0foKajrvOkyc2/OpV7Dga6AzgP+LFXfoCajrrMj01Odrj2h7uccd8ArvNnLqCmo45ynclFN58+HQ/+bcBn8MQcVNNRp9hpcu82p6efHgzEb4F/AJ7ywg+oa5AfEH+eMjn3W+fzzZMB2QUsJKJmCvIDEs0PTa550RDStyz7FkUzxu3BkR8Q15vMeXjW5s7H28yTwN/j+KnD8gNixSqTU0/69sV8fc7cQ/HUlWsAZxvNB3UNajpaXXpMDi01OYUEwC1+AvwdjizLHNQPUNPRarHG5M5PfP6SSXCa/kJxY8a1uLihSE1Ho6bT5MoikztIAPzgduCjwIPOaYCajkbFgyZHbk/KF07au6btFLuwLAY2OzVQtVn5AfbYbHLii1T5nH4JQDQ8ZpT+u0BBfkBiKZgc+KjJicSR9NUm3wc+TMxOapUfEAk/M2P//SQHQcvNiv3ZLgVOw4G3BfIDRs0aM9aX4nFfSglA+bxE0fn9LPBC3P0ANRkpmxfM2C4yYy0kAIPya+AMiqbQy7EdOB0qWiovm7E8w4ytkACUxGPAqcAXgOdi6Qeo6ehwPGfG7lQSavBJAMLhCeAs4Gzg8bj5AWo6OoDHzVidZcZOSABCYS1wAfAx4FZicvyTmo6CGYtbzdhcYMZKSACssBH4OnAExSWjf5QfUDX+aMbgCDMmG5WeEoAo7zq3A5+kaDDdDbTLD7BOu4n1GSb2t+PgYZwSAL94gWLr58OBLwO/kh8QOr8ysT3cxPoFpd3o0brScOkF7jc/RwDnUzxFZkFkfkBvF/mD7b7E82mKRt7jwDtKLws5M335JkXBPo3AuRTPklsATLD5n+X276KQ63YxTvtN0a+h+M6+WakjAfCRT3HoVdXc0K+e76V3/y4o5F2IxXrgWeAZ4rjeQlMAYYHn+iV7A0VD6zTgFCMI6VFd3TQdzbXH7hSrnCn4l4EXgeeBFqWDBCDJtAC/ND+Y4j+ZosN9InACcDxlGrZ9TUfzXa3V+l554DXgVeAVio0zNxgREBIAMcxdch3v7zAbUFzkchwwGzgWmAkcA0wc8kGgvpFCT5dtP2Af8CawFdhC8XCNPwOvGxEQMeb/AYDDAD0ixn7gAAAAAElFTkSuQmCC", + "name": "bccdocs", + "tags": [ + "dapp", + "contractus", + "library" + ], + "version": "1.0.0", + "versions": { + "1.0.0": "QmVffhasxxa4WzpLpEfkVweTWTkqKaYkrfxgwBV78aHH9g" + } + } +} \ No newline at end of file diff --git a/docs/dfs/dfs-interface.rst b/docs/dfs/dfs-interface.rst deleted file mode 100644 index b2bbd5fb..00000000 --- a/docs/dfs/dfs-interface.rst +++ /dev/null @@ -1,156 +0,0 @@ -================================================================================ -DFS Interface -================================================================================ - -.. list-table:: - :widths: auto - :stub-columns: 1 - - * - Interface Name - - DfsInterface - * - Source - - `dfs-interface.ts `_ - -The `DfsInterface `_ is used to add or get files from the distributed file system. It is the only class, that has to be used before having access to a runtime, when using the `createDefaultRuntime`. - -Internally the modules use the `DfsInterface `_ to access data as well. As the actual implementation of the file access may vary, an instance of the interface has to be created beforehand and passed to the `createDefaultRuntime` function. An implementation called `Ipfs `_, that relies on the `IPFS framework `_ is included as in the package. - ------------------------------------------------------------------------------- - -.. _dfs_add: - -add -=================== - -.. code-block:: javascript - - dfs.add(name, data); - -add content to ipfs -file content is converted to Buffer (in NodeJS) or an equivalent "polyfill" (in browsers) - ----------- -Parameters ----------- - -#. ``name`` - ``string``: name of the added file -#. ``data`` - ``buffer``: data (as buffer) of the added file - -------- -Returns -------- - -``string``: ipfs hash of the data. - -------- -Example -------- - -.. code-block:: javascript - - const fileHash = await runtime.dfs.add( - 'about-maika-1.txt', - Buffer.from('we have a cat called "Maika"', 'utf-8'), - ); - console.log(fileHash); - // Output: - // 0x695adc2137f1f069ff697aa287d0eae486521925a23482f180b3ae4e6dbf8d70 - ------------------------------------------------------------------------------- - -.. _dfs_addMultiple: - -addMultiple -=================== - -.. code-block:: javascript - - dfs.addMultiple(files); - -Multiple files can be added at once. This way of adding should be preferred for performance reasons, when adding files, as requests are combined. - ----------- -Parameters ----------- - -#. ``files`` - ``FileToAdd[]``: array with files to add - -------- -Returns -------- - -``Promise`` resolves to ``string[]``: ipfs hash array of the data. - -------- -Example -------- - -.. code-block:: javascript - - const fileHashes = await runtime.dfs.addMultiple([{ - path: 'about-maika-1.txt', - content: Buffer.from('we have a cat called "Maika"', 'utf-8'), - }, { - path: 'about-maika-2.txt', - content: Buffer.from('she can be grumpy from time to time"', 'utf-8'), - } - ]); - console.dir(fileHashes); - // Output: - // [ '0x695adc2137f1f069ff697aa287d0eae486521925a23482f180b3ae4e6dbf8d70', - // '0x6b85c8b24b59b12a630141143c05bbf40a8adc56a8753af4aa41ebacf108b2e7' ] - ------------------------------------------------------------------------------- - - -.. _dfs_get: - -get -=================== - -.. code-block:: javascript - - dfs.get(hash, returnBuffer); - -get data from ipfs by ipfs hash - ----------- -Parameters ----------- - -#. ``hash`` - ``string``: ipfs hash (or bytes32 encoded) of the data -#. ``returnBuffer`` - ``bool``: should the function return the plain buffer, defaults to ``false`` - -------- -Returns -------- - -``Promise`` resolves to ``string | buffer``: data as text or buffer. - -------- -Example -------- - -.. code-block:: javascript - - const fileBuffer = await runtime.dfs.get('0x695adc2137f1f069ff697aa287d0eae486521925a23482f180b3ae4e6dbf8d70'); - console.log(fileBuffer.toString('utf-8')); - // Output: - // we have a cat called "Maika" - ------------------------------------------------------------------------------- - -= Additional Components = -========================== - -Interfaces -================ - -.. _dfs_FileToAdd: - ----------- -FileToAdd ----------- - -#. ``path`` - ``string``: name of the added file -#. ``content`` - ``buffer``: data (as buffer) of the added file \ No newline at end of file diff --git a/docs/dfs/ipfs.rst b/docs/dfs/ipfs.rst deleted file mode 100644 index 915e5890..00000000 --- a/docs/dfs/ipfs.rst +++ /dev/null @@ -1,314 +0,0 @@ -================================================================================ -IPFS -================================================================================ - -.. list-table:: - :widths: auto - :stub-columns: 1 - - * - Class Name - - Ipfs - * - Implements - - `DfsInterface `_ - * - Extends - - `Logger `_ - * - Source - - `ipfs.ts `_ - * - Tests - - `ipfs.spec.ts `_ - - -This is `DfsInterface `_ implementation, that relies on the `IPFS `_ framework. - -.. _ipfs_constructor: - -constructor -================================================================================ - -.. code-block:: typescript - - new Ipfs(options); - -Creates a new IPFS instance. - ----------- -Parameters ----------- - -#. ``options`` - ``IpfsOptions``: options for IPFS constructor. - * ``remoteNode`` - ``any``: ipfs-api instance to remote server - * ``cache`` - |source dfsCache|_ (optional): |source dfsCache|_ instance - * ``log`` - ``Function`` (optional): function to use for logging: ``(message, level) => {...}`` - * ``logLevel`` - |source logLevel|_ (optional): messages with this level will be logged with ``log`` - * ``logLog`` - |source logLogInterface|_ (optional): container for collecting log messages - * ``logLogLevel`` - |source logLevel|_ (optional): messages with this level will be pushed to ``logLog`` - -------- -Returns -------- - -``Ipfs`` instance - -------- -Example -------- - -.. code-block:: typescript - - const ipfs = new Ipfs({ - remoteNode, - cache - }); - - ------------------------------------------------------------------------------- - -.. _ipfs_ipfsHashToBytes32: - -ipfsHashToBytes32 -=================== - -.. code-block:: javascript - - dfs.ipfsHashToBytes32(hash); - -convert IPFS hash to bytes 32 see https://www.reddit.com/r/ethdev/comments/6lbmhy/a_practical_guide_to_cheap_ipfs_hash_storage_in - ----------- -Parameters ----------- - -#. ``hash`` - ``string``: IPFS hash - -------- -Returns -------- - -``string``: bytes32 string. - -------- -Example -------- - -.. code-block:: javascript - - runtime.dfs.ipfsHashToBytes32('QmWmyoMoctfbAaiEs2G46gpeUmhqFRDW6KWo64y5r581Vz') - // returns 0x7D5A99F603F231D53A4F39D1521F98D2E8BB279CF29BEBFD0687DC98458E7F89 - ------------------------------------------------------------------------------- - -.. _ipfs_bytes32ToIpfsHash: - -bytes32ToIpfsHash -=================== - -.. code-block:: javascript - - dfs.bytes32ToIpfsHash(str); - -convert bytes32 to IPFS hash see https://www.reddit.com/r/ethdev/comments/6lbmhy/a_practical_guide_to_cheap_ipfs_hash_storage_in - ----------- -Parameters ----------- - -#. ``str`` - ``string``: bytes32 string - -------- -Returns -------- - -``string``: IPFS Hash. - -------- -Example -------- - -.. code-block:: javascript - - runtime.dfs.ipfsHashToBytes32('0x7D5A99F603F231D53A4F39D1521F98D2E8BB279CF29BEBFD0687DC98458E7F8') - // returns QmWmyoMoctfbAaiEs2G46gpeUmhqFRDW6KWo64y5r581Vz - ------------------------------------------------------------------------------- - -.. _ipfs_add: - -add -=================== - -.. code-block:: javascript - - dfs.add(name, data); - -add content to ipfs -file content is converted to Buffer (in NodeJS) or an equivalent "polyfill" (in browsers) - ----------- -Parameters ----------- - -#. ``name`` - ``string``: name of the added file -#. ``data`` - ``buffer``: data (as buffer) of the added file - -------- -Returns -------- - -``string``: ipfs hash of the data. - -------- -Example -------- - -.. code-block:: javascript - - const fileHash = await runtime.dfs.add( - 'about-maika-1.txt', - Buffer.from('we have a cat called "Maika"', 'utf-8'), - ); - console.log(fileHash); - // Output: - // 0x695adc2137f1f069ff697aa287d0eae486521925a23482f180b3ae4e6dbf8d70 - ------------------------------------------------------------------------------- - -.. _ipfs_addMultiple: - -addMultiple -=================== - -.. code-block:: javascript - - dfs.addMultiple(files); - -Multiple files can be added at once. This way of adding should be preferred for performance reasons, when adding files, as requests are combined. - ----------- -Parameters ----------- - -#. ``files`` - ``FileToAdd[]``: array with files to add - -------- -Returns -------- - -``Promise`` resolves to ``string[]``: ipfs hash array of the data. - -------- -Example -------- - -.. code-block:: javascript - - const fileHashes = await runtime.dfs.addMultiple([{ - path: 'about-maika-1.txt', - content: Buffer.from('we have a cat called "Maika"', 'utf-8'), - }, { - path: 'about-maika-2.txt', - content: Buffer.from('she can be grumpy from time to time"', 'utf-8'), - } - ]); - console.dir(fileHashes); - // Output: - // [ '0x695adc2137f1f069ff697aa287d0eae486521925a23482f180b3ae4e6dbf8d70', - // '0x6b85c8b24b59b12a630141143c05bbf40a8adc56a8753af4aa41ebacf108b2e7' ] - ------------------------------------------------------------------------------- - -.. _ipfs_pinFileHash: - -pinFileHash -=================== - -.. code-block:: javascript - - dfs.pinFileHash(hash); - -pins file hashes on ipfs cluster - ----------- -Parameters ----------- - -#. ``hash`` - ``string``: filehash of the pinned item - -------- -Returns -------- - -``Promise`` resolves to ``void``: resolved when done. - -------- -Example -------- - -.. code-block:: javascript - - const fileBuffer = await runtime.dfs.pinFileHash('QmWmyoMoctfbAaiEs2G46gpeUmhqFRDW6KWo64y5r581Vz'); - ------------------------------------------------------------------------------- - - -.. _ipfs_get: - -get -=================== - -.. code-block:: javascript - - dfs.get(hash, returnBuffer); - -get data from ipfs by ipfs hash - ----------- -Parameters ----------- - -#. ``hash`` - ``string``: ipfs hash (or bytes32 encoded) of the data -#. ``returnBuffer`` - ``bool``: should the function return the plain buffer, defaults to ``false`` - -------- -Returns -------- - -``Promise`` resolves to ``string | buffer``: data as text or buffer. - -------- -Example -------- - -.. code-block:: javascript - - const fileBuffer = await runtime.dfs.get('0x695adc2137f1f069ff697aa287d0eae486521925a23482f180b3ae4e6dbf8d70'); - console.log(fileBuffer.toString('utf-8')); - // Output: - // we have a cat called "Maika" - ------------------------------------------------------------------------------- - -= Additional Components = -========================= - -Interfaces -================ - -.. _ipfs_FileToAdd: - ----------- -FileToAdd ----------- - -#. ``path`` - ``string``: name of the added file -#. ``content`` - ``buffer``: data (as buffer) of the added file - -.. required for building markup - -.. |source dfsCache| replace:: ``DfsCacheInterface`` -.. _source dfsCache: /dfs/dfs-interface.html - -.. |source logLevel| replace:: ``LogLevel`` -.. _source logLevel: /common/logger.html#loglevel - -.. |source logLogInterface| replace:: ``LogLogInterface`` -.. _source logLogInterface: /common/logger.html#logloginterface \ No newline at end of file diff --git a/docs/dfs/ipld.rst b/docs/dfs/ipld.rst index b7a2e93a..1df7cc0b 100644 --- a/docs/dfs/ipld.rst +++ b/docs/dfs/ipld.rst @@ -9,10 +9,10 @@ IPLD * - Class Name - Ipld * - Extends - - `Logger `_ + - `Logger <../common/logger.html>`_ * - Source - `ipld.ts `_ - * - Tests + * - Examples - `ipld.spec.ts `_ @@ -176,7 +176,7 @@ To retrieve data from IPLD trees, use the `bytes32` hash from storing the data: // Output: // { personalInfo: { firstName: 'eris' } } -For info about the ``Ipld.purgeCryptoInfo`` part see :doc:`Encryption `. +For info about the ``Ipld.purgeCryptoInfo`` part see :doc:`Encryption <../encryption/index>`. The second argument is the path inside the tree. Passing '' means "retrieve data from root level". To get more specifc data, provide a path: diff --git a/docs/encryption/cryptor-aes-blob.rst b/docs/encryption/cryptor-aes-blob.rst index a91023a0..aa29ee5e 100644 --- a/docs/encryption/cryptor-aes-blob.rst +++ b/docs/encryption/cryptor-aes-blob.rst @@ -11,10 +11,10 @@ Cryptor - AES Blob * - Implements - `Cryptor `_ * - Extends - - `Logger `_ + - `Logger <../common/logger.html>`_ * - Source - `aes-blob.ts `_ - * - Tests + * - Examples - `aes-blob.spec.ts `_ The `AES Blob `_ cryptor encodes and decodes content with aes-cbc. diff --git a/docs/encryption/cryptor-aes-ecb.rst b/docs/encryption/cryptor-aes-ecb.rst index fed009e8..b1e305a6 100644 --- a/docs/encryption/cryptor-aes-ecb.rst +++ b/docs/encryption/cryptor-aes-ecb.rst @@ -11,10 +11,10 @@ Cryptor - AES ECB * - Implements - `Cryptor `_ * - Extends - - `Logger `_ + - `Logger <../common/logger.html>`_ * - Source - `aes-ecb.ts `_ - * - Tests + * - Examples - `aes-ecb.spec.ts `_ The `AES ECB `_ cryptor encodes and decodes content with aes-ecb. diff --git a/docs/encryption/cryptor-aes.rst b/docs/encryption/cryptor-aes.rst index ab313e8b..8fcfc1e2 100644 --- a/docs/encryption/cryptor-aes.rst +++ b/docs/encryption/cryptor-aes.rst @@ -11,10 +11,10 @@ Cryptor - AES CBC * - Implements - `Cryptor `_ * - Extends - - `Logger `_ + - `Logger <../common/logger.html>`_ * - Source - `aes.ts `_ - * - Tests + * - Examples - `aes.spec.ts `_ The `AES `_ cryptor encodes and decodes content with aes-cbc. diff --git a/docs/encryption/cryptor-unencrypted.rst b/docs/encryption/cryptor-unencrypted.rst deleted file mode 100644 index 259ab8ab..00000000 --- a/docs/encryption/cryptor-unencrypted.rst +++ /dev/null @@ -1,197 +0,0 @@ -================================================================================ -Cryptor - Unencrypted -================================================================================ - -.. list-table:: - :widths: auto - :stub-columns: 1 - - * - Class Name - - Unencrypted - * - Implements - - `Cryptor `_ - * - Extends - - `Logger `_ - * - Source - - `unencrypted.ts `_ - -The `Unencrypted `_ cryptor encodes and decodes content "unencrypted" this means no encryption is applied to the content. So simply the content is public, only HEX encoded. - ------------------------------------------------------------------------------- - -.. _cryptor_unencrypted_constructor: - -constructor -================================================================================ - -.. code-block:: typescript - - new Unencrypted(options); - -Creates a new Unencrypted instance. - ----------- -Parameters ----------- - -#. ``options`` - ``UnencryptedOptions``: options for Unencrypted constructor. - * ``log`` - ``Function`` (optional): function to use for logging: ``(message, level) => {...}`` - * ``logLevel`` - |source logLevel|_ (optional): messages with this level will be logged with ``log`` - * ``logLog`` - |source logLogInterface|_ (optional): container for collecting log messages - * ``logLogLevel`` - |source logLevel|_ (optional): messages with this level will be pushed to ``logLog`` - -------- -Returns -------- - -``Unencrypted`` instance - -------- -Example -------- - -.. code-block:: typescript - - const unencrypted = new Unencrypted(); - ------------------------------------------------------------------------------- - -.. _cryptor_unencrypted_getCryptoInfo: - -getCryptoInfo -=================== - -.. code-block:: javascript - - cryptor.getCryptoInfo(originator); - -create new crypto info for this cryptor - ----------- -Parameters ----------- - -#. ``originator`` - ``string``: originator or context of the encryption - -------- -Returns -------- - -``CryptoInfo``: details about encryption for originator with this cryptor. - -------- -Example -------- - -.. code-block:: javascript - - const cryptor = new Unencrypted(); - const cryptoInfo = cryptor.getCryptoInfo('0x123'); - ------------------------------------------------------------------------------- - -.. _cryptor_unencrypted_generateKey: - -generateKey -=================== - -.. code-block:: javascript - - cryptor.generateKey(); - -generate key for cryptor/decryption - -------- -Returns -------- - -Promise resolves to ``string``: key used for encryption. - -------- -Example -------- - -.. code-block:: javascript - - const cryptor = new Unencrypted(); - const cryptoInfo = cryptor.generateKey(); - ------------------------------------------------------------------------------- - -.. _cryptor_unencrypted_encrypt: - -encrypt -=================== - -.. code-block:: javascript - - cryptor.encrypt(message, options); - -'encrypt' a message (serializes message) - ----------- -Parameters ----------- - -#. ``message`` - ``string``: message which should be encrypted -#. ``options`` - ``any``: cryptor options - * ``key`` - ``string``: key used for encryption - -------- -Returns -------- - -Promise resolves to ``string``: encrypted message. - -------- -Example -------- - -.. code-block:: javascript - - const cryptor = new Unencrypted(); - const cryptoInfo = cryptor.encrypt('Hello World', { key: '0x12345' }); - ------------------------------------------------------------------------------- - -.. _cryptor_unencrypted_decrypt: - -decrypt -=================== - -.. code-block:: javascript - - cryptor.decrypt(message, options); - -'decrypt' a message (deserializes message) - ----------- -Parameters ----------- - -#. ``message`` - ``Buffer``: message which should be decrypted -#. ``options`` - ``any``: cryptor options - * ``key`` - ``string``: key used for encryption - -------- -Returns -------- - -Promise resolves to ``any``: decrypted message. - -------- -Example -------- - -.. code-block:: javascript - - const cryptor = new Unencrypted(); - const cryptoInfo = cryptor.decrypt('afeweq41f1e61e3f', { key: '0x12345' }); - -.. required for building markup - -.. |source logLevel| replace:: ``LogLevel`` -.. _source logLevel: /common/logger.html#loglevel - -.. |source logLogInterface| replace:: ``LogLogInterface`` -.. _source logLogInterface: /common/logger.html#logloginterface \ No newline at end of file diff --git a/docs/encryption/key-provider.rst b/docs/encryption/key-provider.rst index f133c3a0..33cb9537 100644 --- a/docs/encryption/key-provider.rst +++ b/docs/encryption/key-provider.rst @@ -11,7 +11,7 @@ Key Provider * - Implements - `KeyProviderInterface `_ * - Extends - - `Logger `_ + - `Logger <../common/logger.html>`_ * - Source - `key-provider.ts `_ diff --git a/docs/index.rst b/docs/index.rst index 6328d109..33020c5d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -24,9 +24,3 @@ Welcome to blockchain-core's documentation! encryption/index profile/index -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/docs/profile/business-center-profile.rst b/docs/profile/business-center-profile.rst index a23c174d..34b44516 100644 --- a/docs/profile/business-center-profile.rst +++ b/docs/profile/business-center-profile.rst @@ -9,10 +9,10 @@ Business Center Profile * - Class Name - BusinessCenterProfile * - Extends - - `Logger `_ + - `Logger <../common/logger.html>`_ * - Source - `business-center-profile.ts `_ - * - Tests + * - Examples - `business-center-profile.spec.ts `_ The ``BusinessCenterProfile`` module allows to create profiles in a business center. diff --git a/docs/profile/claims.rst b/docs/profile/claims.rst new file mode 100644 index 00000000..04b6b0a4 --- /dev/null +++ b/docs/profile/claims.rst @@ -0,0 +1,388 @@ +================================================================================ +Claims +================================================================================ + +.. list-table:: + :widths: auto + :stub-columns: 1 + + * - Class Name + - Claims + * - Extends + - `Logger `_ + * - Source + - `claims.ts `_ + * - Tests + - `claims.spec.ts `_ + +The ``Claims`` module allows to + +- issue claims about oneself or about other parties +- confirm or reject claims about oneself + +Claims have a pattern similar to file paths or DNS/ENS domains, a claim for an account called "foo" being an employee of a company called "bar" may look like this: + +``/company/bar/employee/foo`` + +Under this "path" a set of values can be found. These value describe the claim, the subject of the claim and optional its response to it. Basically an ``issuer`` creates a ``claim`` about a ``subject`` The values are: + +- ``claim (name)`` + full path to a claim, for example ``/company/bar/employee/foo``, + settable by the ``subject`` of the parent claim ``/company/bar/employee`` +- ``subject`` + an account, a claim has been issued for, can be a group/wallet or an externally owned account + being the ``subject`` of a ``claim`` basically means to be the owner of the claim and allows to create subclaims below the own claim path +- ``issuer`` + an account (group/wallet or externally owned) that creates a claim, + to be able to issue a claim, the ``issuer`` has to be the ``subject`` of the parent claim ``/company/bar/employee`` +- ``content`` + extra data attached to a ``claim``, the value is of type ``bytes32``, + binary data like files, etc. can be encrypted (if desired) and uploaded to a ``DFS`` and then references as a ``bytes32`` hash +- ``self issued content`` + this represents a ``subjects`` value for a certificate, + ``subjects`` can attach an own value to a claim to show approval or disapproval of a claims value, + for the content to be seen as valid, ``issuers`` content value and ``subjects`` content value must equal +- ``self issed state`` + this represents a ``subjects`` "opinion" about a claim, + values are ``uint8`` range from 0 to 255, the currently used values are: + - 0: unset / no response from ``subject`` + - 1: rejection of claim + - 2: approval of claim + + +-------------------------------------------------------------------------------- + +.. _claims_constructor: + +constructor +================================================================================ + +.. code-block:: typescript + + new Claims(options); + +Creates a new Claims instance. + +Note, that the option properties ``registry`` and ``resolver`` are optional but should be provided +in most cases. As the module allows to create an own ENS structure, that includes an own ENS +registry and an own default resolver for it, setting them beforehand is optional. + +---------- +Parameters +---------- + +#. ``options`` - ``ClaimsOptions``: options for Claims constructor. + * ``contractLoader`` - |source contractLoader|_: |source contractLoader|_ instance + * ``executor`` - |source executor|_: |source executor|_ instance + * ``nameResolver`` - |source nameResolver|_: |source nameResolver|_ instance + * ``log`` - ``Function`` (optional): function to use for logging: ``(message, level) => {...}`` + * ``logLevel`` - |source logLevel|_ (optional): messages with this level will be logged with ``log`` + * ``logLog`` - |source logLogInterface|_ (optional): container for collecting log messages + * ``logLogLevel`` - |source logLevel|_ (optional): messages with this level will be pushed to ``logLog`` + * ``registry`` - ``string`` (optional): contract address of the claims registry + * ``resolver`` - ``string`` (optional): contract address of the claims default resolver + +------- +Returns +------- + +``Claims`` instance + +------- +Example +------- + +.. code-block:: typescript + + const claims = new Claims({ + contractLoader, + executor, + nameResolver, + registry: '0x0000000000000000000000000000000000000001', + resolver: '0x0000000000000000000000000000000000000002', + }); + await mailbox.init(); + + + +-------------------------------------------------------------------------------- + + + += Issuers = +========================== + + + +.. _claims_setClaim: + +setClaim +================================================================================ + +.. code-block:: typescript + + claims.setClaim(issuer, subject, claimName[, claimValue]); + +Sets or creates a claim; this requires the issuer to have permissions for the parent claim (if claim +name seen as a path, the parent 'folder'). + +---------- +Parameters +---------- + +#. ``issuer`` - ``string``: issuer of the claim +#. ``subject`` - ``string``: subject of the claim and the owner of the claim node +#. ``claimName`` - ``string``: name of the claim (full path) +#. ``claimValue`` - ``string`` (optional): bytes32 hash of the claims value, will not be set if omitted + +------- +Returns +------- + +``Promise`` returns ``void``: resolved when done + +------- +Example +------- + +.. code-block:: typescript + + await claims.setClaim(accounts[0], accounts[1], '/company'); + + + +-------------------------------------------------------------------------------- + +.. _claims_getClaim: + +getClaim +================================================================================ + +.. code-block:: typescript + + claims.getClaim(claimName); + +Gets claim information for a claim name. + +---------- +Parameters +---------- + +#. ``claimName`` - ``string``: name (/path) of a claim + +------- +Returns +------- + +``Promise`` returns ``any``: claim info, contains: issuer, name, selfIssuedState, selfIssuedValue, status, +subject, value + +------- +Example +------- + +.. code-block:: typescript + + await claims.setClaim(accounts[0], accounts[1], '/company'); + console.dir(await claims.getClaim('/company')); + // Output: + { issuer: '0x0000000000000000000000000000000000000001', + name: '/company', + selfIssuedState: '0', + selfIssuedValue: '0x0000000000000000000000000000000000000000000000000000000000000000', + status: 3, + subject: '0x0000000000000000000000000000000000000002', + value: '0x0000000000000000000000000000000000000000000000000000000000000000' } + + + + + +-------------------------------------------------------------------------------- + +.. _claims_deleteClaim: + +deleteClaim +================================================================================ + +.. code-block:: typescript + + claims.deleteClaim(issuer, claimName); + +Delete a claim. This requires the **issuer** to have permissions for the parent claim (if claim name seen as a path, the parent 'folder'). Subjects of a claim may only delete it, if they are the issuer as well. If not, they can only react to it by confirming or rejecting the claim. + +---------- +Parameters +---------- + +#. ``issuer`` - ``string``: issuer of the claim +#. ``claimName`` - ``string``: name of the claim (full path) + +------- +Returns +------- + +``Promise`` returns ``void``: resolved when done + +------- +Example +------- + +.. code-block:: typescript + + await claims.setClaim(accounts[0], accounts[1], '/company'); + await claims.deleteClaim(accounts[0], '/company'); + + + +-------------------------------------------------------------------------------- + + + += Subjects = +========================== + + + +.. _claims_confirmClaim: + +confirmClaim +================================================================================ + +.. code-block:: typescript + + claims.confirmClaim(subject, claimName[, claimValue]); + +Confirms a claim; this can be done, it a claim has been issued for a subject and the subject wants to confirms it. + +---------- +Parameters +---------- + +#. ``subject`` - ``string``: account, that approves the claim +#. ``claimName`` - ``string``: name of the claim (full path) +#. ``claimValue`` - ``string`` (optional): bytes32 hash of the claim value; this is the subjects value for the claim and has to be the as the issuers value for the claim, will not be set if omitted + +------- +Returns +------- + +``Promise`` returns ``void``: resolved when done + +------- +Example +------- + +.. code-block:: typescript + + await claims.setClaim(accounts[0], accounts[1], '/company'); + await claims.confirmClaim(accounts[1], '/company'); + + + +-------------------------------------------------------------------------------- + +.. _claims_rejectClaim: + +rejectClaim +================================================================================ + +.. code-block:: typescript + + claims.rejectClaim(subject, claimName[, claimValue]); + +Rejects a claim; this can be done, it a claim has been issued for a subject and the subject wants to +reject it. + +---------- +Parameters +---------- + +#. ``subject`` - ``string``: account, that approves the claim +#. ``claimName`` - ``string``: name of the claim (full path) +#. ``claimValue`` - ``string`` (optional): bytes32 hash of the claim value; this is the subjects value for the claim and may differ from the issuers value for the claim + +------- +Returns +------- + +``Promise`` returns ``void``: resolved when done + +------- +Example +------- + +.. code-block:: typescript + + await claims.setClaim(accounts[0], accounts[1], '/company'); + await claims.rejectClaim(accounts[1], '/company'); + + + +-------------------------------------------------------------------------------- + + + += Deployment = +========================== + + + +.. _claims_createStructure: + +createStructure +================================================================================ + +.. code-block:: typescript + + claims.createStructure(accountId); + +Create a new claims structure; this includes a new registry and a default resolver for it. This +isn't required for creating a module instance, its is solely used for creating new structures on the +blockchain. + +---------- +Parameters +---------- + +#. ``accountId`` - ``string``: account, that execute the transaction and owner of the new registry + +------- +Returns +------- + +``Promise`` returns ``any``: object with properties 'registry' and 'resolver', that are web3js +contract instances + +------- +Example +------- + +.. code-block:: typescript + + const claimsStructure = await claims.createStructure(accountId); + console.log(claimsStructure.registry.options.address); + // Output: + // 0x000000000000000000000000000000000000000a + console.log(claimsStructure.resolver.options.address); + // Output: + // 0x000000000000000000000000000000000000000b + + + +.. required for building markup + +.. |source contractLoader| replace:: ``ContractLoader`` +.. _source contractLoader: /contracts/contract-loader.html + +.. |source executor| replace:: ``Executor`` +.. _source executor: /blockchain/executor.html + +.. |source logLevel| replace:: ``LogLevel`` +.. _source logLevel: /common/logger.html#loglevel + +.. |source logLogInterface| replace:: ``LogLogInterface`` +.. _source logLogInterface: /common/logger.html#logloginterface + +.. |source nameResolver| replace:: ``NameResolver`` +.. _source nameResolver: /blockchain/name-resolver.html \ No newline at end of file diff --git a/docs/profile/index.rst b/docs/profile/index.rst index 1fc51377..827b735b 100644 --- a/docs/profile/index.rst +++ b/docs/profile/index.rst @@ -11,6 +11,7 @@ Profile onboarding key-exchange mailbox + claims Profiles are personal data for accounts. They can be shared with other accounts or used for storing own data. This section contains modules for maintaining profile and interacting with profiles from other accounts. diff --git a/docs/profile/key-exchange.rst b/docs/profile/key-exchange.rst index 8c525df5..a4181193 100644 --- a/docs/profile/key-exchange.rst +++ b/docs/profile/key-exchange.rst @@ -9,10 +9,10 @@ Key Exchange * - Class Name - KeyExchange * - Extends - - `Logger `_ + - `Logger <../common/logger.html>`_ * - Source - `keyExchange.ts `_ - * - Tests + * - Examples - `keyExchange.spec.ts `_ The ``KeyExchange`` module is used to exchange communication keys between two parties, assuming that both have created a profile and have a public facing partial Diffie Hellman key part (the combination of their own secret and the shared secret). The key exchange consists of three steps: diff --git a/docs/profile/mailbox.rst b/docs/profile/mailbox.rst index be783394..641c01dc 100644 --- a/docs/profile/mailbox.rst +++ b/docs/profile/mailbox.rst @@ -9,10 +9,10 @@ Mailbox * - Class Name - Mailbox * - Extends - - `Logger `_ + - `Logger <../common/logger.html>`_ * - Source - `mailbox.ts `_ - * - Tests + * - Examples - `mailbox.spec.ts `_ The `Mailbox `_ module is used for sending and retrieving bmails (blockchain mails) to other even.network members. Sending regular bmails between to parties requires them to have completed a `Key Exchange `_ before being able to send encrypted messages. When exchanging the keys, bmails are encrypted with a commonly known key, that is only valid is this case and the underlying messages, that contain the actual keys are encrypted with Diffie Hellman keys, to ensure, that keys are exchanged in a safe manner (see `Key Exchange `_ for details). diff --git a/docs/profile/onboarding.rst b/docs/profile/onboarding.rst index 223a1532..c9207c59 100644 --- a/docs/profile/onboarding.rst +++ b/docs/profile/onboarding.rst @@ -9,10 +9,10 @@ Onboarding * - Class Name - Onboarding * - Extends - - `Logger `_ + - `Logger <../common/logger.html>`_ * - Source - `onboarding.ts `_ - * - Tests + * - Examples - `onboarding.spec.ts `_ The onboarding process is used to enable users to invite other users, where no blockchain account id is known. It allows to send an email to such contacts, that contains a link. This link points to a evan.network ÐApp, that allows accept the invitation by either creating a new account or by accepting it with an existing account. diff --git a/docs/profile/profile.rst b/docs/profile/profile.rst index 9fd14c75..1f6f9377 100644 --- a/docs/profile/profile.rst +++ b/docs/profile/profile.rst @@ -9,10 +9,10 @@ Profile * - Class Name - Profile * - Extends - - `Logger `_ + - `Logger <../common/logger.html>`_ * - Source - `profile.ts `_ - * - Tests + * - Examples - `profile.spec.ts `_ A users profile is its personal storage for diff --git a/package.json b/package.json index 6ea0b10e..97c0c27e 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,8 @@ { - "license": "AGPL-3.0-only", - "author": "contractus", + "author": "evan GmbH", "dependencies": { - "@evan.network/dbcp": "^1.0.3", - "@evan.network/smart-contracts-admin": "^1.0.0", - "@evan.network/smart-contracts-core": "git@github.com:evannetwork/smart-contracts-core.git#develop", + "@evan.network/dbcp": "^1.2.0", + "@evan.network/smart-contracts-core": "^1.0.3", "@types/node": "8.0.53", "ajv": "^5.5.1", "babel-plugin-transform-es3-property-literals": "^6.22.0", @@ -78,6 +76,7 @@ "typescript", "API" ], + "license": "AGPL-3.0-only", "main": "dist/index.js", "name": "@evan.network/api-blockchain-core", "repository": { @@ -97,5 +96,5 @@ "testunitbrk": "env-cmd ./.env.local npm run build && mocha --inspect-brk -r ts-node/register $*" }, "types": "./dist/index.d.ts", - "version": "1.0.2" -} + "version": "1.1.0" +} \ No newline at end of file diff --git a/scripts/buildContracts.js b/scripts/buildContracts.js index 96625ddf..8f00b564 100644 --- a/scripts/buildContracts.js +++ b/scripts/buildContracts.js @@ -23,9 +23,9 @@ on other blockchains than evan.network. For more information, please contact evan GmbH at this address: https://evan.network/license/ + */ -const smartContractsAdmin = require('@evan.network/smart-contracts-admin'); const smartContractsCore = require('@evan.network/smart-contracts-core'); @@ -35,7 +35,7 @@ const solc = new smartContractsCore.Solc({ }); try { - solc.ensureCompiled([smartContractsAdmin.getContractsPath()]); + solc.ensureCompiled(); } catch(ex) { console.error(`building contracts failed with: ${ex.msg || ex}${ex.stack ? '; ' + ex.stack : ''}`); -} +} \ No newline at end of file diff --git a/scripts/bundle.js b/scripts/bundle.js index cd62a88c..1f3a4ca1 100644 --- a/scripts/bundle.js +++ b/scripts/bundle.js @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ const fs = require('fs'); diff --git a/scripts/bundles.js b/scripts/bundles.js index c01ad29e..6f06e9dd 100644 --- a/scripts/bundles.js +++ b/scripts/bundles.js @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ module.exports = [ diff --git a/scripts/discify.js b/scripts/discify.js index bac2bd46..d2c7bf11 100644 --- a/scripts/discify.js +++ b/scripts/discify.js @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ const fs = require('fs'); diff --git a/src/bundles/bcc/bcc.ts b/src/bundles/bcc/bcc.ts index f7877b37..cf240da4 100644 --- a/src/bundles/bcc/bcc.ts +++ b/src/bundles/bcc/bcc.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ require('babel-polyfill'); @@ -68,6 +68,7 @@ import { Onboarding } from '../../onboarding'; import { Profile } from '../../profile/profile'; import { RightsAndRoles } from '../../contracts/rights-and-roles'; import { Sharing } from '../../contracts/sharing'; +import { ServiceContract } from '../../contracts/service-contract/service-contract'; /**************************************************************************************************/ @@ -179,13 +180,14 @@ export interface ProfileBundleOptions { export interface ProfileInstance { // profile exports + dataContract: DataContract, ipldInstance: Ipld, keyExchange: KeyExchange, + keyProvider: KeyProvider, mailbox: Mailbox, profile: Profile, + serviceContract: ServiceContract, sharing: Sharing, - dataContract: DataContract, - keyProvider: KeyProvider, // core exports coreInstance: CoreInstance, @@ -197,14 +199,15 @@ export interface BCBundleOptions { } export interface BCInstance { - ensDomain: string, bcAddress: string, - businessCenter: any, - bcRoles: RightsAndRoles, - ipld: Ipld, bcProfiles: BusinessCenterProfile, + bcRoles: RightsAndRoles, + businessCenter: any, + dataContract: DataContract, description: any, - dataContract: DataContract + ensDomain: string, + ipld: Ipld, + serviceContract: ServiceContract, } /**************************************************************************************************/ @@ -438,6 +441,19 @@ const create = function(options: ProfileBundleOptions): ProfileInstance { logLogLevel }); + const serviceContract = new ServiceContract({ + cryptoProvider: coreInstance.description.cryptoProvider, + dfs: coreInstance.dfs, + executor, + keyProvider: (options.keyProvider), + loader: coreInstance.contractLoader, + nameResolver: coreInstance.nameResolver, + sharing: sharing, + web3: coreInstance.web3, + logLog, + logLogLevel + }); + const profile = new Profile({ ipld: ipldInstance, nameResolver: coreInstance.nameResolver, @@ -456,13 +472,14 @@ const create = function(options: ProfileBundleOptions): ProfileInstance { return { // profile exports + dataContract, ipldInstance, keyExchange, + keyProvider: options.keyProvider, mailbox, profile, + serviceContract, sharing, - keyProvider: options.keyProvider, - dataContract, // core exports coreInstance: coreInstance }; @@ -556,6 +573,19 @@ async function createBC(options: BCBundleOptions) { logLogLevel }); + const serviceContract = new ServiceContract({ + cryptoProvider: CoreRuntime.description.cryptoProvider, + dfs: CoreRuntime.dfs, + executor: CoreRuntime.executor, + keyProvider: ProfileRuntime.keyProvider, + loader: CoreRuntime.contractLoader, + nameResolver: nameResolver, + sharing: ProfileRuntime.sharing, + web3: CoreRuntime.web3, + logLog, + logLogLevel + }); + const description = await CoreRuntime.description.getDescriptionFromEns(ensDomain); return { @@ -566,7 +596,8 @@ async function createBC(options: BCBundleOptions) { ipld, bcProfiles, description: (description), - dataContract + dataContract, + serviceContract, }; } @@ -592,7 +623,7 @@ const isAccountOnboarded = async function(account: string): Promise { try { const ensName = CoreRuntime.nameResolver.getDomainName(CoreRuntime.nameResolver.config.domains.profile); const address = await CoreRuntime.nameResolver.getAddress(ensName); - const contract = CoreRuntime.nameResolver.contractLoader.loadContract('ProfileIndex', address); + const contract = CoreRuntime.nameResolver.contractLoader.loadContract('ProfileIndexInterface', address); const hash = await CoreRuntime.nameResolver.executor.executeContractCall(contract, 'getProfile', account, { from: account, }); if (hash === '0x0000000000000000000000000000000000000000') { diff --git a/src/bundles/bcc/dbcp.json b/src/bundles/bcc/dbcp.json index 54c2b037..8b38169f 100644 --- a/src/bundles/bcc/dbcp.json +++ b/src/bundles/bcc/dbcp.json @@ -1,15 +1,15 @@ { "public": { - "author": "contractus", + "author": "evan GmbH", "dapp": { "dependencies": { - "smartcontracts": "^1.0.2" + "smartcontracts": "^1.0.3" }, "entrypoint": "bcc.js", "files": [ "bcc.js" ], - "origin": "QmeQP32Xdm5BxMTzH1SuN3qGdnLYNRLhS7jQmyUDqvcUqa", + "origin": "QmZx1nM2Z8PUMQkAhDYu6jUiXuf3t5E9oUB8sdkHymTHTB", "type": "library" }, "description": "Contractus for loading ens entries and it's data...", @@ -19,13 +19,14 @@ "contractus", "library" ], - "version": "1.0.2", + "version": "1.1.0", "versions": { "0.1.0": "QmTsY7ASbvxATLnEemHZQ8oQha64ujYe9VXbDCouDk7Xtp", "0.9.0": "Qmbw3yX82TVN9WhsRyeaRpd89M9XXL1pds9GgqJL29ohar", "1.0.0": "QmcECAYTqmKP5AQwkKaCiov77KhgpNLTawAN3tmBCHQeTi", "1.0.1": "QmQNVUFewk95FFkuA62E2TVZNV9w3L6ybMK3b82wyJpg25", - "1.0.2": "QmdC3NTNRPCs2VTrEQx1RNL6LoaDzhQLpa4nsAMA61sM7i" + "1.0.2": "QmdC3NTNRPCs2VTrEQx1RNL6LoaDzhQLpa4nsAMA61sM7i", + "1.1.0": "QmRNmLB6FnTqFXRY9kA3SKJRvFg8avHw5u6pAwcKT6TX9M" } } } \ No newline at end of file diff --git a/src/claims/claims.spec.ts b/src/claims/claims.spec.ts new file mode 100644 index 00000000..5232e5ff --- /dev/null +++ b/src/claims/claims.spec.ts @@ -0,0 +1,163 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ +*/ + +import 'mocha'; +import { expect, use } from 'chai'; +import chaiAsPromised = require('chai-as-promised'); + +import { + ContractLoader, + Executor, +} from '@evan.network/dbcp'; + +import { accounts } from '../test/accounts'; +import { Claims, ClaimsStatus, } from './claims'; +import { TestUtils } from '../test/test-utils'; + +use(chaiAsPromised); + + +describe('Claims handler', function() { + let claims: Claims; + let contractLoader: ContractLoader; + let executor: Executor; + let web3: any; + + before(async () => { + web3 = TestUtils.getWeb3(); + executor = await TestUtils.getExecutor(web3); + contractLoader = await TestUtils.getContractLoader(web3); + claims = await TestUtils.getClaims(web3); + await claims.createStructure(accounts[0]); + }); + + after(async () => { + web3.currentProvider.connection.close(); + }); + + describe('when creating basic contracts', () => { + let claimsContracts; + + it('can add a claim', async () => { + await claims.setClaim(accounts[0], accounts[1], '/company'); + expect(await claims.getClaim('/company')).to.have.property('status', ClaimsStatus.Issued); + }); + + it('cannot add a claim, if parent node isn\'t owned by issuer', async () => { + const promise = claims.setClaim(accounts[1], accounts[0], '/company'); + await expect(promise).to.be.rejected; + }); + + it('can add subclaim paths', async () => { + await claims.setClaim(accounts[0], accounts[0], '/company'); + await claims.setClaim(accounts[0], accounts[0], '/company/b-s-s'); + await claims.setClaim(accounts[0], accounts[0], '/company/b-s-s/employee'); + await claims.setClaim(accounts[0], accounts[1], '/company/b-s-s/employee/swo'); + expect(await claims.getClaim('/company/b-s-s/employee/swo')).to.have.property('status', ClaimsStatus.Issued); + }); + + it('cannot add subclaim, when a node is not owned by issuer', async () => { + await claims.setClaim(accounts[0], accounts[0], '/company'); + await claims.setClaim(accounts[0], accounts[1], '/company/b-s-s'); + const promise = claims.setClaim(accounts[0], accounts[0], '/company/b-s-s/employee'); + await expect(promise).to.be.rejected; + }); + + it('can confirm a subclaim paths with the subject user', async () => { + await claims.setClaim(accounts[0], accounts[0], '/company'); + await claims.setClaim(accounts[0], accounts[0], '/company/b-s-s'); + await claims.setClaim(accounts[0], accounts[0], '/company/b-s-s/employee'); + await claims.setClaim(accounts[0], accounts[1], '/company/b-s-s/employee/swo'); + await claims.confirmClaim(accounts[1], '/company/b-s-s/employee/swo'); + expect(await claims.getClaim('/company/b-s-s/employee/swo')).to.have.property('status', ClaimsStatus.Confirmed); + }); + + it('cannot confirm a subclaim paths with a non-subject user', async () => { + await claims.setClaim(accounts[0], accounts[0], '/company'); + await claims.setClaim(accounts[0], accounts[0], '/company/b-s-s'); + await claims.setClaim(accounts[0], accounts[0], '/company/b-s-s/employee'); + await claims.setClaim(accounts[0], accounts[1], '/company/b-s-s/employee/swo'); + const promise = claims.confirmClaim(accounts[0], '/company/b-s-s/employee/swo'); + await expect(promise).to.be.rejected; + }); + + it('can reject a subclaim paths with the subject user', async () => { + await claims.setClaim(accounts[0], accounts[0], '/company'); + await claims.setClaim(accounts[0], accounts[0], '/company/b-s-s'); + await claims.setClaim(accounts[0], accounts[0], '/company/b-s-s/employee'); + await claims.setClaim(accounts[0], accounts[1], '/company/b-s-s/employee/swo'); + await claims.rejectClaim(accounts[1], '/company/b-s-s/employee/swo'); + expect(await claims.getClaim('/company/b-s-s/employee/swo')).to.have.property('status', ClaimsStatus.Rejected); + }); + + it('cannot reject a subclaim paths with non-subject user', async () => { + await claims.setClaim(accounts[0], accounts[0], '/company'); + await claims.setClaim(accounts[0], accounts[0], '/company/b-s-s'); + await claims.setClaim(accounts[0], accounts[0], '/company/b-s-s/employee'); + await claims.setClaim(accounts[0], accounts[1], '/company/b-s-s/employee/swo'); + const promise = claims.rejectClaim(accounts[0], '/company/b-s-s/employee/swo'); + await expect(promise).to.be.rejected; + }); + + it('rejects using a different resolver than registered', async () => { + // ensure claim (with default resolver) has been issued + await claims.setClaim(accounts[0], accounts[0], '/company'); + // try to use an unregistered resolver + const unregisteredResolver = await executor.createContract( + 'ClaimsPublicResolver', + [ claims.contracts.registry.options.address ], + { from: accounts[0], gas: 2000000, } + ); + let promise = executor.executeContractTransaction( + claims.contracts.registry, + 'setResolver', + { from: accounts[0], }, + claims.options.nameResolver.namehash('company'), + unregisteredResolver.options.address, + ); + await expect(promise).to.be.rejected; + // check, that we can use a proper resolver + promise = executor.executeContractTransaction( + claims.contracts.registry, + 'setResolver', + { from: accounts[0], }, + claims.options.nameResolver.namehash('company'), + claims.contracts.resolver.options.address, + ); + await expect(promise).to.be.fulfilled; + }); + + it('allows to delete a certificate', async() => { + await claims.setClaim(accounts[0], accounts[0], '/company'); + await claims.setClaim(accounts[0], accounts[0], '/company/b-s-s'); + await claims.setClaim(accounts[0], accounts[0], '/company/b-s-s/employee'); + await claims.setClaim(accounts[0], accounts[1], '/company/b-s-s/employee/swo'); + await claims.deleteClaim(accounts[0], '/company/b-s-s/employee/swo'); + expect(await claims.getClaim('/company/b-s-s/employee/swo')).to.have.property('status', ClaimsStatus.None); + }); + }); +}); diff --git a/src/claims/claims.ts b/src/claims/claims.ts new file mode 100644 index 00000000..a085fa7d --- /dev/null +++ b/src/claims/claims.ts @@ -0,0 +1,356 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ +*/ + +import coder = require('web3-eth-abi'); + + +const nullBytes32 = '0x0000000000000000000000000000000000000000000000000000000000000000'; +const nullAddress = '0x0000000000000000000000000000000000000000'; + +import { + ContractLoader, + Description, + EventHub, + Executor, + Logger, + LoggerOptions, + NameResolver, +} from '@evan.network/dbcp'; + +export enum ClaimsStatus { + /** + * empty subject + */ + None, + /** + * self issued state is 1, values may match + */ + Rejected, + /** + * issued by both, self issued state is 2, values match + */ + Confirmed, + /** + * issued by a non-issuer parent claim holder, self issued state is 0 + */ + Issued, + /** + * value from issuer and subject (self issued) missmatch + */ + ValueMissmatch, + /** + * subject set, but value and/or states do not fall within expected range + */ + Unknown, +} + + +export interface ClaimsOptions extends LoggerOptions { + contractLoader: ContractLoader; + executor: Executor; + nameResolver: NameResolver; + registry?: string; + resolver?: string; +} + +/** + * Claims helper + * + * @class Sharing (name) + */ +export class Claims extends Logger { + contracts: any; + options: ClaimsOptions; + + constructor(options: ClaimsOptions) { + super(options); + this.options = options; + if (options.registry && options.resolver) { + this.loadContracts(options.registry, options.resolver); + } + } + + /** + * create a new claims structure; this includes a new registry and a default resolver for it + * + * @param {string} accountId account, that execute the transaction and owner of the + * new registry + * @return {Promise} object with properties 'registry' and 'resolver', that are web3js + * contract instances + */ + public async createStructure(accountId: string): Promise { + // create ens / claims registry + const registry = await this.options.executor.createContract( + 'ClaimsENS', [], { from: accountId, gas: 1000000, }); + + // create claims resolver and point it to ens + const resolver = await this.options.executor.createContract( + 'ClaimsPublicResolver', [ registry.options.address ], { from: accountId, gas: 2000000, }); + + // register resolver as accepted in ens + await this.options.executor.executeContractTransaction( + registry, 'setAcceptedResolverState', { from: accountId, }, resolver.options.address, true); + + this.contracts = { registry, resolver, }; + return this.contracts; + } + + /** + * confirms a claim; this can be done, it a claim has been issued for a subject and the subject + * wants to confirms it + * + * @param {string} subject account, that approves the claim + * @param {string} claimName name of the claim (full path) + * @param {string} claimValue bytes32 hash of the claim value; this is the subjects + * value for the claim and has to be the as the issuers + * value for the claim + * @return {Promise} resolved when done + */ + public async confirmClaim( + subject: string, claimName: string, claimValue?: string): Promise { + return this.respondToClaim(subject, claimName, 2, claimValue); + } + + /** + * delete a claim. This requires the issuer to have permissions for the parent claim (if claim + * name seen as a path, the parent 'folder'). Subjects of a claim may only delete it, if they are + * the issuer as well. If not, they can only react to it by confirming or rejecting the claim. + * + * @param {string} issuer issuer of the claim; only the issuer can delete a claim + * @param {string} claimName name of the claim (full path) + * @return {Promise} resolved when done + */ + public async deleteClaim(issuer: string, claimName: string): Promise { + // create required hashes, etc + const [ ensPath, nodeHash ] = this.getClaimProperties(claimName); + const [_, node, parent] = /([^.]+)\.?(.*)/.exec(ensPath); + const parentHash = parent ? this.options.nameResolver.namehash(parent) : nullBytes32; + // get resolver (if any) + const resolverAddress = await this.options.executor.executeContractCall( + this.contracts.registry, + 'resolver', + nodeHash, + ); + const resolver = resolverAddress !== nullAddress ? + this.options.contractLoader.loadContract('ClaimsPublicResolver', resolverAddress) : null; + + await Promise.all([ + // remove owner (== subject) + (await this.options.executor.executeContractCall(this.contracts.registry, 'owner', nodeHash) !== nullAddress ? + this.options.executor.executeContractTransaction( + this.contracts.registry, + 'setSubnodeOwner', + { from: issuer, }, + parentHash, + this.options.nameResolver.soliditySha3(node), + nullAddress, + ) : null + ), + // clear resolver for node + resolver ? this.options.executor.executeContractTransaction( + this.contracts.registry, + 'setResolver', + { from: issuer, }, + nodeHash, + nullAddress, + ) : null, + // remove addr (== subject) + resolver && (await this.options.executor.executeContractCall(resolver, 'addr', nodeHash) !== nullAddress ? + this.options.executor.executeContractTransaction( + resolver, + 'setAddr', + { from: issuer, }, + nodeHash, + nullAddress, + ) : null + ), + // remov content (== claim value) + resolver && (await this.options.executor.executeContractCall(resolver, 'content', nodeHash) !== nullBytes32 ? + this.options.executor.executeContractTransaction( + resolver, + 'setContent', + { from: issuer, }, + nodeHash, + nullBytes32, + ) : null + ), + ]); + } + + /** + * gets claim information for a claim name + * + * @param {string} claimName name (/path) of a claim + * @return {Promise} claim info, contains: issuer, name, selfIssuedState, selfIssuedValue, + * status, subject, value + */ + public async getClaim(claimName: string): Promise { + const [ ensPath, nodeHash ] = this.getClaimProperties(claimName); + const resolverAddress = await this.options.executor.executeContractCall( + this.contracts.registry, 'resolver', nodeHash); + if (resolverAddress === nullAddress) { + return { status: ClaimsStatus.None, }; + } + const resolver = this.options.contractLoader.loadContract( + 'ClaimsPublicResolver', resolverAddress); + const [ value, issuer, [ subject, selfIssuedState, selfIssuedValue ]] = await Promise.all([ + this.options.executor.executeContractCall(resolver, 'content', nodeHash), + this.options.executor.executeContractCall(this.contracts.registry, 'owner', nodeHash), + (async() => { + const addr = await this.options.executor.executeContractCall(resolver, 'addr', nodeHash); + return await Promise.all([ + addr, + this.options.executor.executeContractCall(resolver, 'selfIssuedState', nodeHash, addr), + this.options.executor.executeContractCall(resolver, 'selfIssuedContent', nodeHash, addr), + ]); + })(), + ]); + const claim = { + issuer, + name: claimName, + selfIssuedState, + selfIssuedValue, + status: ClaimsStatus.Unknown, + subject, + value, + }; + if (subject === nullAddress) { + claim.status = ClaimsStatus.None; + } else if (selfIssuedState === '1') { + claim.status = ClaimsStatus.Rejected; + } else if (selfIssuedState === '0') { + claim.status = ClaimsStatus.Issued + } else if (selfIssuedState === '2' && value === selfIssuedValue) { + claim.status = ClaimsStatus.Confirmed; + } else if (value !== selfIssuedValue) { + claim.status = ClaimsStatus.ValueMissmatch; + } + return claim; + } + + /** + * sets or creates a claim; this requires the issuer to have permissions for the parent claim (if + * claim name seen as a path, the parent 'folder') + * + * @param {string} issuer issuer of the claim + * @param {string} subject subject of the claim and the owner of the claim node + * @param {string} claimName name of the claim (full path) + * @param {string} claimValue bytes32 hash of the claim value + * @return {Promise} resolved when done + */ + public async setClaim( + issuer: string, subject: string, claimName: string, claimValue?: string): Promise { + // transform to ens like path (use dots, remove leading '/') + // /company/b-s-s/employee/aik --> aik.employee.b-s-s.company + const [ ensPath, nodeHash ] = this.getClaimProperties(claimName); + // split into node laben and parent path + // e.g. '/company/b-s-s/employee/aik' --> 'aik' and 'employee.b-s-s.company' (ens like path) + const [_, node, parent] = /([^.]+)\.?(.*)/.exec(ensPath); + // check parent owner + const parentHash = parent ? this.options.nameResolver.namehash(parent) : nullBytes32; + const owner = await this.options.executor.executeContractCall( + this.contracts.registry, + 'owner', + parentHash, + ); + if (owner !== issuer) { + const msg = `trying to set claim ${claimName} with account ${issuer}, ` + + `but parent claim ${parent} not owned by ${issuer}`; + this.log(msg, 'error'); + throw new Error(msg); + } + await Promise.all([ + this.options.executor.executeContractTransaction( + this.contracts.registry, + 'setSubnodeOwner', // (bytes32 node, bytes32 label, address owner) + { from: issuer, }, + parentHash, + this.options.nameResolver.soliditySha3(node), + subject, + ), + this.options.executor.executeContractTransaction( + this.contracts.registry, + 'setResolver', + { from: issuer, }, + nodeHash, + this.contracts.resolver.options.address, + ), + this.options.executor.executeContractTransaction( + this.contracts.resolver, + 'setAddr', + { from: issuer, }, + nodeHash, + subject, + ), + claimValue ? this.options.executor.executeContractTransaction( + this.contracts.resolver, + 'setContent', + { from: issuer, }, + nodeHash, + claimValue, + ) : null, + ]); + } + + /** + * reject a claim; this can be done, it a claim has been issued for a subject and the subject + * wants to reject it + * + * @param {string} subject account, that approves the claim + * @param {string} claimName name of the claim (full path) + * @param {string} claimValue bytes32 hash of the claim value; this is the subjects + * value for the claim and may differ from the issuers + * value for the claim + * @return {Promise} resolved when done + */ + public async rejectClaim(subject: string, claimName: string, claimValue?: string): Promise { + return this.respondToClaim(subject, claimName, 1, claimValue); + } + + private getClaimProperties(claimName: string): string[] { + const ensPath = claimName.split('/').slice(1).reverse().join('.'); + return [ensPath, this.options.nameResolver.namehash(ensPath)]; + } + + private loadContracts(registry, resolver) { + this.contracts = { + registry: this.options.contractLoader.loadContract('ENS', registry), + resolver: this.options.contractLoader.loadContract('ClaimsPublicResolver', resolver), + }; + } + + private async respondToClaim( + subject: string, claimName: string, state: number, claimValue?: string): Promise { + const [ _, nodeHash ] = this.getClaimProperties(claimName); + await Promise.all([ + await this.options.executor.executeContractTransaction( + this.contracts.resolver, 'setSelfIssuedState', { from: subject, }, nodeHash, state), + claimValue ? this.options.executor.executeContractTransaction( + this.contracts.resolver, 'setSelfIssuedContent', { from: subject, }, nodeHash, claimValue) : null, + ]); + } +} diff --git a/src/common/utils.ts b/src/common/utils.ts index 36163765..a0a5aa75 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ /** diff --git a/src/config.ts b/src/config.ts index 8f8ccdf3..98ece84b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ const config = { @@ -36,7 +36,8 @@ const config = { admin: 'admin', eventhub: 'eventhub', profile: 'profile', - mailbox: 'mailbox' + mailbox: 'mailbox', + wallet: 'wallet', }, domains: { root: ['ensRoot'], @@ -54,7 +55,7 @@ const config = { accountId: '0x063fB42cCe4CA5448D69b4418cb89E663E71A139', }, }, - alwaysAutoGasLimit: 1.1, + alwaysAutoGasLimit: 10, } export { config } \ No newline at end of file diff --git a/src/contracts/base-contract/base-contract.spec.ts b/src/contracts/base-contract/base-contract.spec.ts index 8596b1ad..06f5bc0a 100644 --- a/src/contracts/base-contract/base-contract.spec.ts +++ b/src/contracts/base-contract/base-contract.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; @@ -205,7 +205,7 @@ describe('BaseContract', function() { await expect(promise).to.be.rejected; }); - it('can have its state set by users that are not in the contract', async () => { + it('cannot have its state set by users that are not in the contract', async () => { const contractId = await baseContract.createUninitialized( 'testdatacontract', accounts[0], diff --git a/src/contracts/base-contract/base-contract.ts b/src/contracts/base-contract/base-contract.ts index 71b381d1..0f25305f 100644 --- a/src/contracts/base-contract/base-contract.ts +++ b/src/contracts/base-contract/base-contract.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import { diff --git a/src/contracts/business-center/business-center.spec.ts b/src/contracts/business-center/business-center.spec.ts index 987898ac..96330d59 100644 --- a/src/contracts/business-center/business-center.spec.ts +++ b/src/contracts/business-center/business-center.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; diff --git a/src/contracts/data-contract/data-contract.spec.ts b/src/contracts/data-contract/data-contract.spec.ts index 1dcc4340..12ce365f 100644 --- a/src/contracts/data-contract/data-contract.spec.ts +++ b/src/contracts/data-contract/data-contract.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; @@ -77,7 +77,7 @@ describe('DataContract', function() { "name": "Data Contract Sample", "description": "reiterance oxynitrate sat alternize acurative", "version": "0.1.0", - "author": "contractus", + "author": "evan GmbH", } }; /* tslint:enable:quotemark */ diff --git a/src/contracts/data-contract/data-contract.ts b/src/contracts/data-contract/data-contract.ts index 0ff154a6..a258d0b7 100644 --- a/src/contracts/data-contract/data-contract.ts +++ b/src/contracts/data-contract/data-contract.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import crypto = require('crypto'); @@ -182,7 +182,6 @@ export class DataContract extends BaseContract { hashes = await Promise.all(hashes.map(hash => this.encryptHash(hash, dataContract, accountId))); } // store as is - console.dir(hashes); await this.options.executor.executeContractTransaction( dataContract, 'addListEntries', diff --git a/src/contracts/executor-agent.spec.ts b/src/contracts/executor-agent.spec.ts new file mode 100644 index 00000000..75f240db --- /dev/null +++ b/src/contracts/executor-agent.spec.ts @@ -0,0 +1,207 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ +*/ + +import 'mocha'; +import { expect, use } from 'chai'; +import chaiAsPromised = require('chai-as-promised'); + +import { + ContractLoader, + LogLevel, + SignerInternal, + SignerInterface, +} from '@evan.network/dbcp'; + +import { accounts } from '../test/accounts'; +import { ExecutorAgent } from './executor-agent'; +import { TestUtils } from '../test/test-utils' + + +const agentUser = '0xa60F5EAfBb782793d7589bc5F55BfA3a599B182d'; +const ensDomain = '0xa4f4bc00d00f32992d5115ca850962b66537252c8367317a7d70a85c59cc1954'; +const ensMainAccount = '0x4a6723fC5a926FA150bAeAf04bfD673B056Ba83D'; +const randomAccount = `0x${Math.floor(Math.random() * 255 * 255 * 255).toString(16).padStart(40, '0')}`; + +let contract; +let contractLoader; +let password; +let web3; + +use(chaiAsPromised); + +describe('Executor handler', function() { + this.timeout(300000); + let executor: ExecutorAgent; + + before(async () => { + web3 = TestUtils.getWeb3(); + const accountStore = TestUtils.getAccountStore({}); + contractLoader = await TestUtils.getContractLoader(web3); + const signer = new SignerInternal({ + accountStore, + contractLoader, + config: {}, + web3, + }); + executor = new ExecutorAgent({ + config: {}, + contractLoader, + signer, + web3, + }); + password = web3.utils.soliditySha3('fluffy cat is fluffy'); + }); + + after(() => { + web3.currentProvider.connection.close(); + }); + + it('should be able to call a contract method', async () => { + const sampleContract = contractLoader.loadContract('AbstractENS', TestUtils.getConfig().nameResolver.ensAddress); + const owner = await executor.executeContractCall(sampleContract, 'owner', ensDomain); + expect(owner).to.eq(ensMainAccount); + }); + + it('should be able to create a contract', async () => { + // create token for creating contract + const token = await executor.generateToken(password, [{ signature: 'Owned', }]); + executor.token = token; + contract = await executor.createContract('Owned', [], { gas: 2000000, }); + expect(contract).not.to.be.undefined; + const owner = await executor.executeContractCall(contract, 'owner'); + expect(owner).to.eq(agentUser); + }); + + it('should be able to perform transactions', async () => { + let owner = await executor.executeContractCall(contract, 'owner'); + expect(owner).to.eq(agentUser); + + // grant tx token + const token = await executor.generateToken(password, [{ contract, functionName: 'transferOwnership', }]); + executor.token = token; + // try to transfer ownership + await executor.executeContractTransaction(contract, 'transferOwnership', { gas: 2000000, }, randomAccount); + owner = await executor.executeContractCall(contract, 'owner'); + expect(owner.toLowerCase()).to.eq(randomAccount); + }); + + describe('when managing tokens', () => { + it('should allow contract creation and transactions, when token has been granted', async () => { + // create token for creating contract + let token = await executor.generateToken(password, [{ signature: 'Owned', }]); + executor.token = token; + // allowed, as token has been set + const localContract = await executor.createContract('Owned', [], { gas: 2000000, }); + expect(localContract).not.to.be.undefined; + let owner = await executor.executeContractCall(localContract, 'owner'); + expect(owner).to.eq(agentUser); + + // grant tx token + token = await executor.generateToken(password, [{ contract: localContract, functionName: 'transferOwnership', }]); + executor.token = token; + // allowed, as token has been set + await executor.executeContractTransaction(localContract, 'transferOwnership', { gas: 2000000, }, randomAccount); + owner = await executor.executeContractCall(localContract, 'owner'); + expect(owner.toLowerCase()).to.eq(randomAccount); + }); + + it('should not allow contract creation, when token has been granted', async () => { + // allowed, as token has been set + delete executor.token; + const localContractPromise = executor.createContract('Owned', [], { gas: 2000000, }); + await expect(localContractPromise).to.be.rejected; + }); + + it('should not allow transactions, when token has not been granted', async () => { + // create token for creating contract + const token = await executor.generateToken(password, [{ signature: 'Owned', }]); + executor.token = token; + // allowed, as token has been set + const localContract = await executor.createContract('Owned', [], { gas: 2000000, }); + expect(localContract).not.to.be.undefined; + const owner = await executor.executeContractCall(localContract, 'owner'); + expect(owner).to.eq(agentUser); + + // allowed, as token has been set + delete executor.token; + const txPromise = executor.executeContractTransaction(localContract, 'transferOwnership', { gas: 2000000, }, randomAccount); + await expect(txPromise).to.be.rejected; + }); + + it('should allow multiple transactions, when matching token has been granted', async () => { + // create token for creating contract + let token = await executor.generateToken(password, [{ signature: 'Owned', }]); + executor.token = token; + // allowed, as token has been set + const localContract = await executor.createContract('Owned', [], { gas: 2000000, }); + expect(localContract).not.to.be.undefined; + const owner = await executor.executeContractCall(localContract, 'owner'); + expect(owner).to.eq(agentUser); + + // grant tx token + token = await executor.generateToken(password, [{ contract: localContract, functionName: 'transferOwnership', count: 3, }]); + executor.token = token; + // allowed (1/3), as token has been set + await executor.executeContractTransaction(localContract, 'transferOwnership', { gas: 2000000, }, agentUser); + // allowed (2/3), as token has been set + await executor.executeContractTransaction(localContract, 'transferOwnership', { gas: 2000000, }, agentUser); + // allowed (3/3), as token has been set + await executor.executeContractTransaction(localContract, 'transferOwnership', { gas: 2000000, }, agentUser); + // will fail + const txPromise = executor.executeContractTransaction(localContract, 'transferOwnership', { gas: 2000000, }, agentUser); + await expect(txPromise).to.be.rejected; + }); + + it('rejects contract creations, when value has been set', async() => { + // create token for creating contract + let token = await executor.generateToken(password, [{ signature: 'Owned', }]); + executor.token = token; + // fails, as value has been given + const localContractPromise = executor.createContract('Owned', [], { gas: 2000000, value: 1000, }); + await expect(localContractPromise).to.be.rejected; + }); + + it('rejects contract transactions, when value has been set', async() => { + // create token for creating contract + let token = await executor.generateToken(password, [{ signature: 'Owned', }]); + executor.token = token; + // allowed, as token has been set + const localContract = await executor.createContract('Owned', [], { gas: 2000000, }); + expect(localContract).not.to.be.undefined; + let owner = await executor.executeContractCall(localContract, 'owner'); + expect(owner).to.eq(agentUser); + + // grant tx token + token = await executor.generateToken(password, [{ contract: localContract, functionName: 'transferOwnership', }]); + executor.token = token; + + // fails, as value has been given + const txPromise = executor.executeContractTransaction(localContract, 'transferOwnership', { gas: 2000000, value: 1000, }, randomAccount); + await expect(txPromise).to.be.rejected; + }); + }); +}); diff --git a/src/contracts/executor-agent.ts b/src/contracts/executor-agent.ts new file mode 100644 index 00000000..913c741d --- /dev/null +++ b/src/contracts/executor-agent.ts @@ -0,0 +1,253 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ +*/ + +import request = require('request'); + +import { + ContractLoader, + EventHub, + Executor, + ExecutorOptions, + SignerInterface, +} from '@evan.network/dbcp'; + + +/** + * options for executor agent instance + */ +export interface ExecutorAgentOptions extends ExecutorOptions { + contractLoader: ContractLoader; + agentUrl?: string; + token?: string; +} + + +/** + * helper for calling contract functions, executing transactions + * + * @class ExecutorAgent (name) + */ +export class ExecutorAgent extends Executor { + agentUrl: string; + config: any; + contractLoader: ContractLoader; + defaultOptions: any; + eventHub: EventHub; + signer: SignerInterface; + web3: any; + token: string; + + /** + * note, that the ExecutorAgent requires the "init" function to be called when intending to use the + * EventHub helper for transactions with event return values + */ + constructor(options: ExecutorAgentOptions) { + super(options); + this.config = options.config; + this.contractLoader = options.contractLoader; + this.defaultOptions = options.defaultOptions; + this.signer = options.signer; + this.token = options.token; + this.web3 = options.web3; + this.agentUrl = options.agentUrl || 'http://localhost:8080'; + } + + /** + * creates a contract by contstructing creation transaction and signing it with private key of + * options.from + * + * transactions, that transfer EVEs, will be rejected + * + * @param {string} contractName contract name + * @param {any[]} functionArguments arguments for contract creation, pass empty + * Array if no arguments + * @param {any} inputOptions transaction arguments, having at least .from and + * .gas + * @return {Promise} new contract + */ + public async createContract(contractName: string, functionArguments: any[], inputOptions: any): Promise { + this.log(`starting contract creation for "${contractName}" via agent`, 'debug'); + if (inputOptions.value && parseInt(inputOptions.value, 10)) { + throw new Error('sending funds is not supported by the agent based executor; ' + + `value has been set to ${inputOptions.value} for new contract "${contractName}"`); + } + + // submit to action + const contractId = await new Promise((resolve, reject) => { + request({ + uri: `${this.agentUrl}/api/smart-agents/executor/createContract`, + method: 'POST', + json: true, + body: { + contractName, + functionArguments, + inputOptions, + token: this.token, + }, + }, this.handleRequestResult.bind(this, resolve, reject)) + }); + return this.contractLoader.loadContract(contractName, contractId as string); + } + + + /** + * @brief run the given call from contract + * + * @param {any} contract the target contract + * @param {string} functionName name of the contract function to call + * @param {any[]} args optional array of arguments for contract call. if + * last arguments is {Object}, it is used as the options + * parameter + * @return {Promise} resolves to: {Object} contract calls result + */ + public async executeContractCall(contract: any, functionName: string, ...args): Promise { + this.log(`starting contract call "${functionName}" via agent`, 'debug'); + + // submit to action + return new Promise((resolve, reject) => { + request({ + uri: `${this.agentUrl}/api/smart-agents/executor/executeContractCall`, + method: 'POST', + json: true, + body: { + contractId: contract.options.address, + functionSignature: contract.options.jsonInterface.filter(fun => fun.name === functionName)[0], + functionName, + functionArguments: args, + }, + }, this.handleRequestResult.bind(this, resolve, reject)) + }); + } + + /** + * execute a transaction against the blockchain, handle gas exceeded and return values from + * contract function + * + * transactions, that transfer EVEs, will be rejected + * + * @param {any} contract contract instance + * @param {string} functionName name of the contract function to call + * @param {any} inputOptions currently supported: from, gas, event, + * getEventResult, eventTimeout, estimate, force + * @param {any[]} functionArguments optional arguments to pass to contract + * transaction + * @return {Promise} Promise, that resolves to: no result (if no event to watch was + * given), the event (if event but no getEventResult was given), the + * value returned by getEventResult(eventObject) + */ + public async executeContractTransaction( + contract: any, functionName: string, inputOptions: any, ...functionArguments: any[]): Promise { + this.log(`starting contract transaction "${functionName}" via agent`, 'debug'); + if (inputOptions.value && parseInt(inputOptions.value, 10)) { + throw new Error('sending funds is not supported by the agent based executor; ' + + `value has been set to ${inputOptions.value} for tx "${functionName}"`); + } + + // submit to action + return new Promise((resolve, reject) => { + request({ + uri: `${this.agentUrl}/api/smart-agents/executor/executeContractTransaction`, + method: 'POST', + json: true, + body: { + contractId: contract.options.address, + functionSignature: contract.options.jsonInterface.filter(fun => fun.name === functionName)[0], + functionName, + options: inputOptions, + functionArguments, + token: this.token, + }, + }, this.handleRequestResult.bind(this, resolve, reject)) + }); + } + + /** + * will throw, as sending funds directly is not supported by the walled based executor + * + * @param {any} inputOptions transaction options, having at least from, to and + * value + * @return {Promise} resolved when done + */ + public async executeSend(inputOptions): Promise { + throw new Error(`sending funds is not supported by the agent based executor`); + } + + /** + * initialize executor + * + * @param {any} options object with the property "eventHub" (of the type EventHub) + */ + public init(options: any) { + this.eventHub = options.eventHub; + } + + /** + * generate a new token for transactions (or contract creations) + * + * @param {string} password password for token creation + * @param {any[]} functions array of function signatures as abi objects + * @return {Promise} new token + */ + public async generateToken(password, functions): Promise { + // patch zero id contract addresses, if required + const updatedFunctions = functions.map((fun) => { + const newFun = { + contractId: fun.contractId || '0x0000000000000000000000000000000000000000', + signature: fun.signature || null, + count: fun.count || 1, + }; + if (fun.contract) { + newFun.contractId = fun.contract.options.address; + if (fun.functionName) { + newFun.signature = fun.contract.options.jsonInterface.filter(ff => ff.name === fun.functionName)[0]; + } + } + return newFun; + }) + return new Promise((resolve, reject) => { + request({ + uri: `${this.agentUrl}/api/smart-agents/executor/generateToken`, + method: 'POST', + json: true, + body: { + password, + functions: updatedFunctions, + }, + }, this.handleRequestResult.bind(this, resolve, reject)) + }) as Promise; + } + + private handleRequestResult(resolve, reject, error, msg, body) { + if (error) { + reject(error); + } else if (body.error) { + reject(body.error); + } else { + resolve(body.result); + } + } +} diff --git a/src/contracts/executor-wallet.spec.ts b/src/contracts/executor-wallet.spec.ts new file mode 100644 index 00000000..3715280b --- /dev/null +++ b/src/contracts/executor-wallet.spec.ts @@ -0,0 +1,168 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ +*/ + +import 'mocha'; +import { expect, use } from 'chai'; +import chaiAsPromised = require('chai-as-promised'); + +import { + ContractLoader, + DfsInterface, + Executor, + Ipfs, + NameResolver, + SignerInternal, +} from '@evan.network/dbcp'; + +import { accounts } from '../test/accounts'; +import { config } from '../config'; +import { CryptoProvider } from '../encryption/crypto-provider'; +import { ExecutorWallet } from './executor-wallet'; +import { sampleContext, TestUtils } from '../test/test-utils'; +import { Sharing } from './sharing'; +import { Wallet } from './wallet'; + +use(chaiAsPromised); + + +describe('Signer Wallet', function() { + let dfs: DfsInterface; + let contractLoader: ContractLoader; + let executor: Executor; + let executorWallet: ExecutorWallet; + let nameResolver: NameResolver; + let wallet: Wallet; + let web3: any; + + before(async () => { + web3 = TestUtils.getWeb3(); + dfs = await TestUtils.getIpfs(); + wallet = await TestUtils.getWallet(web3, dfs); + await wallet.create(accounts[0], accounts[0], [accounts[0]]); + // wallet.load('0x581B4a37Ced787Ac93b54527E5A01158571759eB'); + executor = await TestUtils.getExecutor(web3); + contractLoader = await TestUtils.getContractLoader(web3); + nameResolver = await TestUtils.getNameResolver(web3); + executorWallet = await TestUtils.getExecutorWallet(web3, wallet, dfs); + const eventHub = await TestUtils.getEventHub(web3); + executor.eventHub = eventHub; + executorWallet.eventHub = eventHub; + }); + + after(async () => { + await dfs.stop(); + web3.currentProvider.connection.close(); + }); + + describe('when submitting transactions via wallet', () => { + it('can instantly submit transactions', async () => { + // create test contract and hand over to wallet + const testContract = await executor.createContract('Owned', [], { from: accounts[0], gas: 200000, }); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(accounts[0]); + await executor.executeContractTransaction(testContract, 'transferOwnership', { from: accounts[0], }, wallet.walletContract.options.address); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(wallet.walletContract.options.address); + + await executorWallet.executeContractTransaction(testContract, 'transferOwnership', { from: accounts[0], autoGas: 1.1, }, accounts[1]); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(accounts[1]); + }); + + it('cannot submit transactions, when not in owners group', async () => { + // create test contract and hand over to wallet + const testContract = await executor.createContract('Owned', [], { from: accounts[0], gas: 200000, }); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(accounts[0]); + + await executor.executeContractTransaction(testContract, 'transferOwnership', { from: accounts[0], autoGas: 1.1, }, wallet.walletContract.options.address); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(wallet.walletContract.options.address); + + const promise = executorWallet.executeContractTransaction(testContract, 'transferOwnership', { from: accounts[1], }, accounts[1]); + await expect(promise).to.be.rejected; + }); + + it('can instantly submit transactions a second time', async () => { + // create test contract and hand over to wallet + const testContract = await executor.createContract('Owned', [], { from: accounts[0], gas: 200000, }); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(accounts[0]); + await executor.executeContractTransaction(testContract, 'transferOwnership', { from: accounts[0], }, wallet.walletContract.options.address); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(wallet.walletContract.options.address); + await executorWallet.executeContractTransaction(testContract, 'transferOwnership', { from: accounts[0], autoGas: 1.1, }, accounts[1]); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(accounts[1]); + }); + + it('can instantly submit transactions with event based result', async () => { + const factoryAddress = await nameResolver.getAddress('testcontract.factory.testbc.evan'); + const factory = contractLoader.loadContract('TestContractFactory', factoryAddress); + const businessCenterDomain = nameResolver.getDomainName(config.nameResolver.domains.businessCenter); + const businessCenterAddress = '0x0000000000000000000000000000000000000000'; + + const data = `I like random numbers, for example: ${Math.random()}`; + const contractId = await executorWallet.executeContractTransaction( + factory, + 'createContract', { + from: accounts[0], + event: { target: 'TestContractFactory', eventName: 'ContractCreated', }, + getEventResult: (event, args) => args.newAddress, + }, + data, + ); + expect(contractId).to.match(/0x[0-9a-f]{40}/i); + const testContract = contractLoader.loadContract('TestContract', contractId); + expect(await executor.executeContractCall(testContract, 'data')).to.eq(data); + }); + + it('can instantly submit transactions with event based result a second time', async () => { + const factoryAddress = await nameResolver.getAddress('testcontract.factory.testbc.evan'); + const factory = contractLoader.loadContract('TestContractFactory', factoryAddress); + const businessCenterDomain = nameResolver.getDomainName(config.nameResolver.domains.businessCenter); + const businessCenterAddress = '0x0000000000000000000000000000000000000000'; + + const data = `I like random numbers, for example: ${Math.random()}`; + const contractId = await executorWallet.executeContractTransaction( + factory, + 'createContract', { + from: accounts[0], + event: { target: 'TestContractFactory', eventName: 'ContractCreated', }, + getEventResult: (event, args) => args.newAddress, + }, + data, + ); + expect(contractId).to.match(/0x[0-9a-f]{40}/i); + const testContract = contractLoader.loadContract('TestContract', contractId); + expect(await executor.executeContractCall(testContract, 'data')).to.eq(data); + }); + + it('can instantly submit transactions a third time', async () => { + // create test contract and hand over to wallet + const testContract = await executor.createContract('Owned', [], { from: accounts[0], gas: 200000, }); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(accounts[0]); + await executor.executeContractTransaction(testContract, 'transferOwnership', { from: accounts[0], }, wallet.walletContract.options.address); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(wallet.walletContract.options.address); + + await executorWallet.executeContractTransaction(testContract, 'transferOwnership', { from: accounts[0], autoGas: 1.1, }, accounts[1]); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(accounts[1]); + }); + }); +}); diff --git a/src/contracts/executor-wallet.ts b/src/contracts/executor-wallet.ts new file mode 100644 index 00000000..559edd58 --- /dev/null +++ b/src/contracts/executor-wallet.ts @@ -0,0 +1,418 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ +*/ + +import { + EventHub, + Executor, + ExecutorOptions, + SignerInterface, +} from '@evan.network/dbcp'; + +import { Wallet } from './wallet'; + + +/** + * options for executor instance + */ +export interface ExecutorWalletOptions extends ExecutorOptions { + wallet: Wallet; +} + + +/** + * helper for calling contract functions, executing transactions, uses wallet for performing + * transactions + * + * @class ExecutorWallet (name) + */ +export class ExecutorWallet extends Executor { + options: ExecutorWalletOptions; + + /** + * note, that the ExecutorWallet requires the "init" function to be called when intending to use the + * EventHub helper for transactions with event return values + */ + constructor(options: ExecutorWalletOptions) { + super(options); + this.options = options; + } + + /** + * @brief run the given call from contract + * + * @param {any} contract the target contract + * @param {string} functionName name of the contract function to call + * @param {any[]} args optional array of arguments for contract call. if + * last arguments is {Object}, it is used as the options + * parameter + * @return {Promise} resolves to: {Object} contract calls result + */ + async executeContractCall(contract: any, functionName: string, ...args): Promise { + this.log(`starting contract call "${functionName}"`, 'debug'); + if (!contract.methods[functionName]) { + throw new Error(`contract does not support method "${functionName}", ` + + `supported methods are ${Object.keys(contract.methods)}`); + } + if (!contract || !contract.options || !contract.options.address) { + throw new Error('contract undefined or contract has no address'); + } + let options; + options = this.defaultOptions ? Object.assign({}, this.defaultOptions) : null; + if (args.length && typeof args[args.length - 1] === 'object') { + // merge options, use wallet address as from + options = Object.assign( + options || {}, + args[args.length - 1], + { from: this.options.wallet.walletContract.options.address, }, + ); + return contract.methods[functionName].apply(contract.methods, args.slice(0, args.length - 1)).call(options); + } else if (options) { + return contract.methods[functionName].apply(contract.methods, args).call(options); + } else { + return contract.methods[functionName].apply(contract.methods, args).call(); + } + } + + /** + * execute a transaction against the blockchain, handle gas exceeded and return values from + * contract function + * + * transactions, that transfer EVEs, will be rejected + * + * @param {any} contract contract instance + * @param {string} functionName name of the contract function to call + * @param {any} inputOptions currently supported: from, gas, event, + * getEventResult, eventTimeout, estimate, force + * @param {any[]} functionArguments optional arguments to pass to contract + * transaction + * @return {Promise} Promise, that resolves to: no result (if no event to watch was + * given), the event (if event but no getEventResult was given), the + * value returned by getEventResult(eventObject) + */ + async executeContractTransaction(contract: any, functionName: string, inputOptions: any, ...functionArguments: any[]): Promise { + // autoGas 1.1 ==> if truthy, enables autoGas 1.1 ==> adds 10% to estimated value capped to current block + // maximum minus 4* the allowed derivation per block - The protocol allows the miner of a block + // to adjust the block gas limit by a factor of 1/1024 (0.0976%) in either direction. + // (http://hudsonjameson.com/2017-06-27-accounts-transactions-gas-ethereum/) makes it + // Math.min(gasEstimated * autoGas, gasLimitCurrentBlock * 255/256) + this.log(`starting contract transaction "${functionName}"`, 'debug'); + if (inputOptions.value && parseInt(inputOptions.value, 10)) { + throw new Error('sending funds is not supported by the wallet based executor; ' + + `value has been set to ${inputOptions.value} for tx "${functionName}"`); + } + if (!this.signer) { + throw new Error('signer is undefined'); + } + if (!contract.methods[functionName]) { + throw new Error(`contract does not support method "${functionName}", ` + + `supported methods are ${Object.keys(contract.methods)}`); + } + if (!contract || !contract.options || !contract.options.address) { + throw new Error('contract undefined or contract has no address'); + } + + // every argument beyond the third is an argument for the contract function + let options = Object.assign({}, this.defaultOptions || {}, inputOptions); + + // strip unrelated option + const validProperties = ['from', 'to', 'gasPrice', 'gas', 'value', 'data', 'nonce']; + Object.keys(options).forEach((option) => { + if (!validProperties.includes(option)) { + delete options[option]; + } + }); + + let autoGas; + if (inputOptions.autoGas) { + autoGas = inputOptions.autoGas; + } else if (this.config && this.config.alwaysAutoGasLimit) { + autoGas = this.config.alwaysAutoGasLimit; + } else { + autoGas = false; + } + + const initialArguments = functionArguments.slice(0); + const logGas = (extraParams) => { + const staticEntries = { + arguments: initialArguments, + contract: contract.address || contract._address, + from: inputOptions.from, + gasEstimated: null, + gasGiven: options.gas, + gasUsed: 0, + status: 'unknown', + transaction: functionName, + transactionHash: null, + }; + const level = 'gasLog'; + this.log(JSON.stringify(Object.assign(staticEntries, extraParams)), level); + } + return new Promise(async (resolve, reject) => { + // keep track of the promise state via variable as we may run into a timeout + let isPending = true; + let transactionHash; + const eventResults = { }; + + // timeout and event listener with this + let subscription; + const stopWatching = async (isError?) => { + return new Promise((resolveStop) => { + setTimeout(() => { + if (inputOptions.event && subscription) { + if (this.eventHub) { + this.eventHub + .unsubscribe({ subscription}) + .catch((ex) => { + this.log(`error occurred while unsubscribing from transaction event; ${ex.message || ex}${ex.stack || ''}`, 'error'); + }) + ; + } else { + reject('passed an event to a transaction but no event hub registered'); + } + } + isPending = false; + resolveStop(); + }, isError ? 1000 : 0); + }); + } + + try { + // timeout rejects promise if not already done so + setTimeout(async () => { + if (isPending) { + await stopWatching(true); + logGas({ status: 'error', message: 'timeout' }); + reject(new Error(`timeout during ${functionName}`)); + } + }, inputOptions.eventTimeout || 300000); + + // if we wait for a 'result', pick this result from event watch and resolve the promise + if (inputOptions.event) { + if (this.eventHub) { + this.eventHub + .subscribe( + inputOptions.event.target, + contract.options.address, + inputOptions.event.eventName, + (event) => true, + (event) => { + if (transactionHash === event.transactionHash) { + // if we have a retriever function, use it, otherwise return entire event object + if (inputOptions.getEventResult) { + resolve(inputOptions.getEventResult(event, event.args || event.returnValues)); + } else { + resolve(event); + } + } else { + // if execution event is fired before callback, + // hold the evenTransaction and trigger resolve within execution callback + eventResults[event.transactionHash] = event; + } + } + ) + .then((result) => { subscription = result; }) + .catch((ex) => { + this.log(`error occurred while subscribing to transaction event; ${ex.message || ex}${ex.stack || ''}`, 'error'); + }) + ; + } else { + this.log('passed an event to a transaction but no event hub registered', 'warning'); + } + } + + // add options and callback function to arguments + functionArguments.push(options); + // const estimationArguments = functionArguments.slice(); + let gasEstimated; + let executeCallback; + const estimationCallback = async (error, gasAmount) => { + gasEstimated = gasAmount; + if (error) { + await stopWatching(true); + logGas({ status: 'error', message: `could not estimate; ${error}` }); + reject(`could not estimate gas usage for ${functionName}: ${error}; ${error.stack}`); + } else if (inputOptions.estimate) { + await stopWatching(); + resolve(gasAmount); + } else if (!inputOptions.force && parseInt(inputOptions.gas, 10) === parseInt(gasAmount, 10)) { + await stopWatching(true); + logGas({ status: 'error', message: 'out of gas estimated' }); + reject(`transaction ${functionName} by ${options.from} would most likely fail`); + } else { + // execute contract function + // recover original from, as estimate converts from to lower case + options.from = inputOptions.from; + // overwrite given gas with estimation plus autoGas factor + if (autoGas) { + this.web3.eth.getBlock('latest', (error, result) => { + if (error) { + reject(`could not get latest block for ${functionName}: ${error}; ${error.stack}`); + } else { + const currentLimit = result.gasLimit; + const gas = Math.floor(Math.min(gasEstimated * autoGas, currentLimit * (255 / 256))); + // const gas = Math.max(Math.floor(Math.min(gasEstimated * autoGas, currentLimit * (255 / 256))), 53528); + logGas({ status: 'autoGas.estimation', gasEstimated: gasEstimated, gasGiven: gas, message: `estimated with ${autoGas}` }); + options.gas = gas; + this.signAndExecuteTransactionViaWallet(contract, functionName, functionArguments.slice(0, -1), Object.assign({}, options), (...args) => { executeCallback.apply(this, args).catch((ex) => { reject(ex); }); }); + } + }); + } else { + this.signAndExecuteTransactionViaWallet(contract, functionName, functionArguments.slice(0, -1), Object.assign({}, options), (...args) => { executeCallback.apply(this, args).catch((ex) => { reject(ex); }); }); + } + } + }; + + executeCallback = async (err, receipt) => { + if (err) { + return reject(`${functionName} failed: ${err}`); + } + try { + // keep transaction hash for checking agains it in event + transactionHash = receipt && receipt.transactionHash ? receipt.transactionHash : ''; + if (err) { + this.log(`${functionName} failed: ${err.message || err}`, 'error'); + logGas({ status: 'error', message: 'transaction submit error', gasEstimated, transactionHash }); + reject(err); + } else { + let optionsGas; + if (typeof options.gas === 'string' && options.gas.startsWith('0x')) { + optionsGas = parseInt(options.gas, 16); + } else { + optionsGas = parseInt(options.gas, 10); + } + if (optionsGas !== receipt.gasUsed) { + logGas({ status: 'success', gasUsed: receipt.gasUsed, gasEstimated, transactionHash }); + // log autoGas entry + if (autoGas) { + logGas({ + status: 'autoGas.success', + gasEstimated, + gasGiven: options.gas, + gasUsed: receipt.gasUsed, + message: `estimated with ${autoGas}`, + }); + } + // if no event to watch for was given, resolve promise here + if (!inputOptions.event || !this.eventHub) { + isPending = false; + resolve(); + } else if (eventResults[transactionHash]) { + await stopWatching(); + if (inputOptions.getEventResult) { + resolve(inputOptions.getEventResult(eventResults[transactionHash], eventResults[transactionHash].args || eventResults[transactionHash].returnValues)); + } else { + resolve(eventResults[transactionHash]); + } + } + } else { + const errorText = 'all gas used up'; + this.log(`${functionName} failed: ${errorText}`, 'error'); + // log autoGas entry + if (autoGas) { + logGas({ + status: 'autoGas.error', + gasEstimated, + gasGiven: options.gas, + gasUsed: receipt.gasUsed, + message: `estimated with ${autoGas}`, + }); + } + if (inputOptions.event && this.eventHub) { + await stopWatching(true); + } + logGas({ + status: 'error', + message: 'transaction failed', + gasUsed: receipt.gasUsed, + gasEstimated, + transactionHash, + }); + reject(errorText); + } + } + } catch (ex) { + return reject(`${functionName} failed: ${ex.message}`); + } + }; + // estimate tx with wallet accountid instead of users account id + const estimateOptions = Object.assign({}, options, { from: this.options.wallet.walletContract.options.address, }); + contract.methods[functionName].apply(contract.methods, initialArguments).estimateGas(estimateOptions, (...args) => { estimationCallback.apply(this, args).catch((ex) => { reject(ex); }); }); + } catch (ex) { + this.log(`${functionName} failed: ${ex.message}`, 'error'); + await stopWatching(true); + logGas({ status: 'error', message: 'transaction could not be started' }); + reject(ex); + } + }); + } + + /** + * will throw, as sending funds directly is not supported by the walled based executor + * + * @param {any} inputOptions transaction options, having at least from, to and + * value + * @return {Promise} resolved when done + */ + async executeSend(inputOptions): Promise { + throw new Error(`sending funds is not supported by the walled based executor`); + } + + /** + * will throw, as creating contracts directly is not supported by the walled based executor + * + * @param {string} contractName contract name + * @param {any[]} functionArguments arguments for contract creation, pass empty + * Array if no arguments + * @param {any} inputOptions transaction arguments, having at least .from and + * .gas + * @return {Promise} new contract + */ + async createContract(contractName: string, functionArguments: any[], inputOptions: any): Promise { + throw new Error(`creating contracts directly is not supported by the walled based executor`); + } + + /** + * create, sing and submit a contract transaction with private key of options.from + * + * @param {any} contract contract instance from api.eth.loadContract(...) + * @param {string} functionName function name + * @param {any[]} functionArguments arguments for contract creation, pass empty Array if + * no arguments + * @param {any} options transaction arguments, having at least .from and + * .gas + * @param {function} handleTxResult callback(error, result) + * @return {void} + */ + private signAndExecuteTransactionViaWallet = (contract, functionName, functionArguments, options, handleTxResult): void => { + this.log(`using wallet ${this.options.wallet.walletContract.options.address} for making transaction "${functionName}"`, 'debug'); + this.options.wallet + .submitTransaction(contract, functionName, options, ...functionArguments) + .then((result) => { handleTxResult(null, result); }) + .catch((error) => { handleTxResult(error); }) + ; + } +} diff --git a/src/contracts/rights-and-roles.spec.ts b/src/contracts/rights-and-roles.spec.ts index 9fb6c27b..99e1b1f2 100644 --- a/src/contracts/rights-and-roles.spec.ts +++ b/src/contracts/rights-and-roles.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; diff --git a/src/contracts/rights-and-roles.ts b/src/contracts/rights-and-roles.ts index 68200a15..e257c823 100644 --- a/src/contracts/rights-and-roles.ts +++ b/src/contracts/rights-and-roles.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import prottle = require('prottle'); diff --git a/src/contracts/service-contract/service-contract.spec.ts b/src/contracts/service-contract/service-contract.spec.ts index e9adf4c3..46737444 100644 --- a/src/contracts/service-contract/service-contract.spec.ts +++ b/src/contracts/service-contract/service-contract.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; @@ -61,107 +61,113 @@ describe('ServiceContract', function() { let web3; const sampleService1 = { serviceName: 'serviceContractService1', - endPoint: 'serviceContractService1', requestParameters: { - required: [ - 'callName', - ], + type: 'object', + additionalProperties: false, properties: { - callName: { - type: 'string', - }, - tags: { - type: 'string', + metadata: { + type: 'object', + additionalProperties: false, + properties: { + author: { type: 'string', }, + privateData: { type: 'object', }, + }, }, - endDate: { - type: 'integer', - }, - allowMultipleAnswers: { - type: 'boolean', - }, - amount: { - type: 'integer', - }, - articleNumber: { - type: 'string', - }, - possibleWeek: { - type: 'integer', - }, - note: { - type: 'string', + payload: { + type: 'object', + additionalProperties: false, + required: [ 'callName', ], + properties: { + callName: { type: 'string', }, + tags: { type: 'string', }, + endDate: { type: 'integer', }, + allowMultipleAnswers: { type: 'boolean', }, + amount: { type: 'integer', }, + articleNumber: { type: 'string', }, + possibleWeek: { type: 'integer', }, + note: { type: 'string', }, + privateData: { type: 'object', }, + }, }, }, }, responseParameters: { + type: 'object', + additionalProperties: false, properties: { - possibleAmount: { - type: 'integer', - }, - price: { - type: 'integer', + metadata: { + type: 'object', + additionalProperties: false, + properties: { + author: { type: 'string', }, + }, }, - possibleDeliveryWeek: { - type: 'integer', - }, - note: { - type: 'string', + payload: { + type: 'object', + additionalProperties: false, + properties: { + possibleAmount: { type: 'integer', }, + price: { type: 'integer', }, + possibleDeliveryWeek: { type: 'integer', }, + note: { type: 'string', }, + }, }, }, }, - updateService: true, }; const sampleService2 = { serviceName: 'serviceContractService2', - endPoint: 'serviceContractService2', requestParameters: { - required: [ - 'callName', - ], + type: 'object', + additionalProperties: false, properties: { - callName: { - type: 'string', - }, - tags: { - type: 'string', - }, - endDate: { - type: 'integer', - }, - allowMultipleAnswers: { - type: 'boolean', - }, - amount: { - type: 'integer', - }, - articleNumber: { - type: 'string', - }, - possibleWeek: { - type: 'integer', - }, - note: { - type: 'string', + metadata: { + type: 'object', + additionalProperties: false, + properties: { + author: { type: 'string', }, + }, }, + payload: { + type: 'object', + additionalProperties: false, + required: [ 'callName', ], + properties: { + callName: { type: 'string', }, + tags: { type: 'string', }, + endDate: { type: 'integer', }, + allowMultipleAnswers: { type: 'boolean', }, + amount: { type: 'integer', }, + articleNumber: { type: 'string', }, + possibleWeek: { type: 'integer', }, + note: { type: 'string', }, + }, + } }, }, responseParameters: { + type: 'object', + additionalProperties: false, properties: { - possibleAmount: { - type: 'integer', + metadata: { + type: 'object', + additionalProperties: false, + properties: { + author: { type: 'string', }, + }, }, - price: { - type: 'integer', - }, - possibleDeliveryWeek: { - type: 'integer', - }, - note: { - type: 'string', + payload: { + type: 'object', + additionalProperties: false, + properties: { + possibleAmount: { type: 'integer', }, + price: { type: 'integer', }, + possibleDeliveryWeek: { type: 'integer', }, + note: { type: 'string', }, + }, }, }, }, - updateService: true, } const sampleCall = { metadata: { @@ -289,6 +295,14 @@ describe('ServiceContract', function() { expect(call).to.deep.eq(sampleCall); }); + it('cannot send a service message, that doesn\'t match the definition', async() => { + const contract = await sc0.create(accounts[0], businessCenterDomain, sampleService1); + const brokenCall = JSON.parse(JSON.stringify(sampleCall)); + brokenCall.payload.someBogus = 123; + const sendCallPromise = sc0.sendCall(contract, accounts[0], brokenCall); + await expect(sendCallPromise).to.be.rejected; + }); + it('can send an answer to a service message', async() => { const contract = await sc0.create(accounts[0], businessCenterDomain, sampleService1); await sc0.inviteToContract(businessCenterDomain, contract.options.address, accounts[0], accounts[2]); @@ -301,6 +315,19 @@ describe('ServiceContract', function() { expect(answer).to.deep.eq(sampleAnswer); }); + it('cannot send an answer to a service message, that doesn\'t match the definition', async() => { + const contract = await sc0.create(accounts[0], businessCenterDomain, sampleService1); + await sc0.inviteToContract(businessCenterDomain, contract.options.address, accounts[0], accounts[2]); + const contentKey = await sharing.getKey(contract.options.address, accounts[0], '*', 0); + await sharing.addSharing(contract.options.address, accounts[0], accounts[2], '*', 0, contentKey); + const callId = await sc0.sendCall(contract, accounts[0], sampleCall, [accounts[2]]); + const call = await sc2.getCall(contract, accounts[0], callId); + const brokenAnswer = JSON.parse(JSON.stringify(sampleAnswer)); + brokenAnswer.payload.someBogus = 123; + const sendAnswerPromise = sc2.sendAnswer(contract, accounts[2], brokenAnswer, callId, call.metadata.author); + await expect(sendAnswerPromise).to.be.rejected; + }); + it('can hold multiple calls', async() => { const sampleCalls = [Math.random(), Math.random(), Math.random()].map((rand) => { const currentSample = JSON.parse(JSON.stringify(sampleCall)); @@ -316,6 +343,23 @@ describe('ServiceContract', function() { expect(await sc0.getCall(contract, accounts[0], 2)).to.deep.eq(sampleCalls[2]); }); + it('allows to retrieve the call owner', async () => { + const sampleCalls = [Math.random(), Math.random(), Math.random()].map((rand) => { + const currentSample = JSON.parse(JSON.stringify(sampleCall)); + currentSample.payload.note += rand; + return currentSample; + }); + const contract = await sc0.create(accounts[0], businessCenterDomain, sampleService1); + for (let currentSample of sampleCalls) { + await sc0.sendCall(contract, accounts[0], currentSample); + } + await sc0.sendCall(contract, accounts[1], sampleCalls[0]); + expect(await sc0.getCallOwner(contract, 0)).to.deep.eq(accounts[0]); + expect(await sc0.getCallOwner(contract, 1)).to.deep.eq(accounts[0]); + expect(await sc0.getCallOwner(contract, 2)).to.deep.eq(accounts[0]); + expect(await sc0.getCallOwner(contract, 3)).to.deep.eq(accounts[1]); + }); + it('does not allow calls to be read by every contract member without extending the sharing', async() => { const blockNr = await web3.eth.getBlockNumber(); const contract = await sc0.create(accounts[0], businessCenterDomain, sampleService1); @@ -453,25 +497,25 @@ describe('ServiceContract', function() { sampleAnswers.push(answer); } - // if using existing contract - contract = loader.loadContract('ServiceContractInterface', '0xdeDca22030f95488E7db80A3aF26A1C122aeCa17'); - - // // if creating new contract - // contract = await sc0.create(accounts[0], businessCenterDomain, sampleService1); - // await sc0.inviteToContract(businessCenterDomain, contract.options.address, accounts[0], accounts[2]); - // const contentKey = await sharing.getKey(contract.options.address, accounts[0], '*', 0); - // await sharing.addSharing(contract.options.address, accounts[0], accounts[2], '*', 0, contentKey); - // let callIndex = 0; - // for (let currentSample of sampleAnswers) { - // console.log(`send test call ${callIndex++}`); - // await sc0.sendCall(contract, accounts[0], currentSample, [accounts[2]]); - // } - // let answerIndex = 0; - // for (let answer of sampleAnswers) { - // console.log(`send test answer ${answerIndex++}`); - // await sc2.sendAnswer(contract, accounts[2], answer, anweredCallId, accounts[0]) - // } - // console.log(contract.options.address); + // // if using existing contract + // contract = loader.loadContract('ServiceContractInterface', '0xdeDca22030f95488E7db80A3aF26A1C122aeCa17'); + + // if creating new contract + contract = await sc0.create(accounts[0], businessCenterDomain, sampleService1); + await sc0.inviteToContract(businessCenterDomain, contract.options.address, accounts[0], accounts[2]); + const contentKey = await sharing.getKey(contract.options.address, accounts[0], '*', 0); + await sharing.addSharing(contract.options.address, accounts[0], accounts[2], '*', 0, contentKey); + let callIndex = 0; + for (let currentSample of sampleAnswers) { + console.log(`send test call ${callIndex++}`); + await sc0.sendCall(contract, accounts[0], currentSample, [accounts[2]]); + } + let answerIndex = 0; + for (let answer of sampleAnswers) { + console.log(`send test answer ${answerIndex++}`); + await sc2.sendAnswer(contract, accounts[2], answer, anweredCallId, accounts[0]) + } + console.log(contract.options.address); }); describe('when retrieving calls', () => { diff --git a/src/contracts/service-contract/service-contract.ts b/src/contracts/service-contract/service-contract.ts index c5eafa62..934e033c 100644 --- a/src/contracts/service-contract/service-contract.ts +++ b/src/contracts/service-contract/service-contract.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import crypto = require('crypto'); @@ -34,6 +34,7 @@ import { Envelope, KeyProviderInterface, Logger, + Validator, } from '@evan.network/dbcp'; import { BaseContract, BaseContractOptions, } from '../base-contract/base-contract'; @@ -42,6 +43,16 @@ import { Sharing } from '../sharing'; const requestWindowSize = 10; +const serviceSchema = { + type: 'object', + additionalProperties: false, + properties: { + serviceName: { type: 'string', }, + requestParameters: { type: 'object', }, + responseParameters: { type: 'object', }, + }, +}; + /** * options for ServiceContract constructor @@ -65,7 +76,8 @@ export class ServiceContract extends BaseContract { private readonly encodingUnencrypted = 'utf-8'; private readonly encodingEncrypted = 'hex'; private readonly encodingUnencryptedHash = 'hex'; - private readonly cryptoAlgorithHashes = 'aesEcb' + private readonly cryptoAlgorithHashes = 'aesEcb'; + private serviceDefinition; constructor(optionsInput: ServiceContractOptions) { super(optionsInput as BaseContractOptions); @@ -125,9 +137,16 @@ export class ServiceContract extends BaseContract { service: any, descriptionDfsHash = '0x0000000000000000000000000000000000000000000000000000000000000000', ): Promise { + // validate service definition + const validator = new Validator({ schema: serviceSchema, }); + const checkFails = validator.validate(service); + if (checkFails !== true) { + throw new Error(`validation of service values failed with: ${JSON.stringify(checkFails)}`); + } + const contractP = (async () => { const contractId = await super.createUninitialized( - 'servizz', accountId, businessCenterDomain, descriptionDfsHash); + 'service', accountId, businessCenterDomain, descriptionDfsHash); return this.options.loader.loadContract('ServiceContractInterface', contractId); })(); @@ -140,7 +159,7 @@ export class ServiceContract extends BaseContract { await this.options.sharing.ensureHashKey(contract.options.address, accountId, accountId, hashKey); // add service after sharing has been added - await this.setService(contract, accountId, service, businessCenterDomain); + await this.setService(contract, accountId, service, businessCenterDomain, true); return contract; } @@ -251,14 +270,17 @@ export class ServiceContract extends BaseContract { return decrypted; } - /** + /** * get all calls from a contract * - * @param {any|string} contract smart contract instance or contract ID + * @param {any|string} contract smart contract instance +or contract ID * @param {string} accountId Ethereum account ID - * @param {number} count number of elements to retrieve + * @param {number} count number of elements to +retrieve * @param {number} offset skip this many elements - * @param {boolean} reverse retrieve last elements first + * @param {boolean} reverse retrieve last elements +first * @return {Promise} the calls */ public async getCalls( @@ -266,23 +288,28 @@ export class ServiceContract extends BaseContract { accountId: string, count = 10, offset = 0, - reverse = false): Promise { + reverse = false): Promise { const serviceContract = (typeof contract === 'object') ? - contract : this.options.loader.loadContract('ServiceContractInterface', contract); + contract: this.options.loader.loadContract('ServiceContractInterface', contract); // get entries - const { entries, indices } = await this.getEntries(serviceContract, 'calls', null, count, offset, reverse); + const { entries, indices } = await this.getEntries(serviceContract, + 'calls', null, count, offset, reverse); // add sharings hashes to sharing module cache indices.forEach((index) => { - this.options.sharing.addHashToCache(contract.options.address, entries[index].sharing, this.numberToBytes32(index)); + this.options.sharing.addHashToCache(serviceContract.options.address, + entries[index].sharing, this.numberToBytes32(index)); }); // decrypt contents + const result = {}; const tasks = indices.map((index) => async () => { const callIdString = this.numberToBytes32(index); - const decryptedHash = await this.decryptHash(entries[index].encryptedHash, serviceContract, accountId, callIdString); - return this.decrypt( + const decryptedHash = await this.decryptHash(entries[index].encryptedHash, serviceContract, + accountId, callIdString); + + result[index] = await this.decrypt( (await this.options.dfs.get(decryptedHash)).toString('utf-8'), serviceContract, accountId, @@ -291,11 +318,13 @@ export class ServiceContract extends BaseContract { ); }); - const decrypted = tasks.length ? await prottle(requestWindowSize, tasks) : []; + if (tasks.length) { + await prottle(requestWindowSize, tasks); + } - return decrypted; + return result; } - + /** * get number of calls of a contract * @@ -309,6 +338,23 @@ export class ServiceContract extends BaseContract { return parseInt(count, 10); } + /** + * gets the owner/creator of a call + * + * @param {any|string} contract contract instance or id + * @param {number} callId id of a call + * @return {Promise} account id of call owner + */ + public async getCallOwner(contract: any|string, callId: number): Promise { + const serviceContract = (typeof contract === 'object') ? + contract : this.options.loader.loadContract('ServiceContractInterface', contract); + return this.options.executor.executeContractCall( + serviceContract, + 'multiSharingsOwner', + `0x${(callId).toString(16).padStart(64, '0')}`, + ) + } + /** * gets the service of a service contract * @@ -327,6 +373,7 @@ export class ServiceContract extends BaseContract { accountId, '*' ); + this.serviceDefinition = decrypted; return decrypted; } @@ -348,14 +395,26 @@ export class ServiceContract extends BaseContract { callAuthor: string): Promise { const serviceContract = (typeof contract === 'object') ? contract : this.options.loader.loadContract('ServiceContractInterface', contract); + + // validate call + if (!this.serviceDefinition) { + // this.serviceDefinition is set and updated via side effects in getService and setService + await this.getService(serviceContract, accountId); + } + const validator = new Validator({ schema: this.serviceDefinition.responseParameters, }); + const checkFails = validator.validate(answer); + if (checkFails !== true) { + throw new Error(`validation of input values failed with: ${JSON.stringify(checkFails)}`); + } + const blockNr = 0; // will be ignored as callAuthor is set const encrypted = await this.encrypt(answer, serviceContract, accountId, '*', blockNr, callAuthor); const stateMd5 = crypto.createHash('md5').update(encrypted).digest('hex'); const answerHash = await this.options.dfs.add(stateMd5, Buffer.from(encrypted)); - const hashKey = await this.options.sharing.getHashKey(contract.options.address, accountId, this.numberToBytes32(callId)); + const hashKey = await this.options.sharing.getHashKey(serviceContract.options.address, accountId, this.numberToBytes32(callId)); const encryptdHash = await this.encryptHash(answerHash, serviceContract, accountId, hashKey); const answerId = await this.options.executor.executeContractTransaction( - contract, + serviceContract, 'sendAnswer', { from: accountId, autoGas: 1.1, @@ -387,6 +446,17 @@ export class ServiceContract extends BaseContract { const serviceContract = (typeof contract === 'object') ? contract : this.options.loader.loadContract('ServiceContractInterface', contract); + // validate call + if (!this.serviceDefinition) { + // this.serviceDefinition is set and updated via side effects in getService and setService + await this.getService(serviceContract, accountId); + } + const validator = new Validator({ schema: this.serviceDefinition.requestParameters, }); + const checkFails = validator.validate(call); + if (checkFails !== true) { + throw new Error(`validation of input values failed with: ${JSON.stringify(checkFails)}`); + } + // create local copy of call for encryption const callCopy = JSON.parse(JSON.stringify(call)); @@ -440,7 +510,7 @@ export class ServiceContract extends BaseContract { const serviceHash = await this.options.dfs.add(stateMd5, Buffer.from(encrypted)); const encryptdHash = await this.encryptHash(serviceHash, serviceContract, accountId, hashKey); const callIdUint256 = parseInt(await this.options.executor.executeContractTransaction( - contract, + serviceContract, 'sendCall', { from: accountId, autoGas: 1.1, @@ -458,13 +528,13 @@ export class ServiceContract extends BaseContract { const callId = this.numberToBytes32(callIdUint256); // keep keys for owner await this.options.sharing.ensureHashKey( - contract.options.address, accountId, accountId, hashKey, null, callId); + serviceContract.options.address, accountId, accountId, hashKey, null, callId); await this.options.sharing.addSharing( - contract.options.address, accountId, accountId, '*', 0, contentKey, null, false, callId); + serviceContract.options.address, accountId, accountId, '*', 0, contentKey, null, false, callId); // if subproperties were encryted, keep them for owner as well for (let propertyName of Object.keys(innerEncryptionData)) { await this.options.sharing.addSharing( - contract.options.address, + serviceContract.options.address, accountId, accountId, propertyName, @@ -476,7 +546,7 @@ export class ServiceContract extends BaseContract { ); } // for each to, add sharing keys - await this.addToCallSharing(contract, accountId, callIdUint256, to, hashKey, contentKey); + await this.addToCallSharing(serviceContract, accountId, callIdUint256, to, hashKey, contentKey); // return id of new call return parseInt(callId, 16); @@ -490,15 +560,26 @@ export class ServiceContract extends BaseContract { * @param {any} service service to set * @param {string} businessCenterDomain domain of the business the service contract * belongs to + * @param {bool} skipValidation (optional) skip validation of service + * definition, validation is enabled by default * @return {Promise} resolved when done */ public async setService( contract: any|string, accountId: string, service: any, - businessCenterDomain: string): Promise { + businessCenterDomain: string, + skipValidation?): Promise { const serviceContract = (typeof contract === 'object') ? contract : this.options.loader.loadContract('ServiceContractInterface', contract); + if (!skipValidation) { + // validate service definition + const validator = new Validator({ schema: serviceSchema, }); + const checkFails = validator.validate(service); + if (checkFails !== true) { + throw new Error(`validation of service definition failed with: ${JSON.stringify(checkFails)}`); + } + } const blockNr = await this.options.web3.eth.getBlockNumber(); const serviceHashP = (async () => { const encrypted = await this.encrypt(service, serviceContract, accountId, '*', blockNr); @@ -511,11 +592,12 @@ export class ServiceContract extends BaseContract { serviceHashP, ]); await this.options.executor.executeContractTransaction( - contract, + serviceContract, 'setService', {from: accountId, autoGas: 1.1, }, businessCenterAddress, encryptdHash, ); + this.serviceDefinition = service; } /** @@ -580,7 +662,7 @@ export class ServiceContract extends BaseContract { private async decryptHash( toDecrypt: string, contract: any, accountId: string, callId?: string): Promise { const dataContract = (typeof contract === 'object') ? - contract : this.options.loader.loadContract('DataContractInterface', contract); + contract : this.options.loader.loadContract('ServiceContractInterface', contract); // decode hash const cryptor = this.options.cryptoProvider.getCryptorByCryptoAlgo(this.cryptoAlgorithHashes); const hashKey = await this.options.sharing.getHashKey(dataContract.options.address, accountId, callId); diff --git a/src/contracts/sharing.spec.ts b/src/contracts/sharing.spec.ts index acd0a3dc..0751db78 100644 --- a/src/contracts/sharing.spec.ts +++ b/src/contracts/sharing.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; diff --git a/src/contracts/sharing.ts b/src/contracts/sharing.ts index a907c5a6..33bdeaae 100644 --- a/src/contracts/sharing.ts +++ b/src/contracts/sharing.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import { diff --git a/src/contracts/wallet.spec.ts b/src/contracts/wallet.spec.ts new file mode 100644 index 00000000..dae39678 --- /dev/null +++ b/src/contracts/wallet.spec.ts @@ -0,0 +1,134 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ +*/ + +import 'mocha'; +import { expect, use } from 'chai'; +import chaiAsPromised = require('chai-as-promised'); + +import { + ContractLoader, + DfsInterface, + Executor, + Ipfs, + NameResolver, +} from '@evan.network/dbcp'; + +import { accounts } from '../test/accounts'; +import { config } from '../config'; +import { CryptoProvider } from '../encryption/crypto-provider'; +import { Sharing } from './sharing'; +import { sampleContext, TestUtils } from '../test/test-utils'; +import { Wallet } from './wallet'; + +use(chaiAsPromised); + + +describe('Wallet handler', function() { + let dfs: DfsInterface; + let contractLoader: ContractLoader; + let executor: Executor; + let wallet: Wallet; + let web3: any; + + before(async () => { + web3 = TestUtils.getWeb3(); + dfs = await TestUtils.getIpfs(); + wallet = await TestUtils.getWallet(web3, dfs); + executor = await TestUtils.getExecutor(web3); + contractLoader = await TestUtils.getContractLoader(web3); + }); + + after(async () => { + await dfs.stop(); + web3.currentProvider.connection.close(); + }); + + it('can create new wallets', async () => { + await wallet.create(accounts[0], accounts[0], [accounts[0]]); + }); + + describe('when managing members', () => { + it('can add members, when admin', async () => { + await wallet.create(accounts[0], accounts[0], [accounts[0]]); + expect(await wallet.getOwners()).to.deep.eq([accounts[0]]); + await wallet.addOwner(accounts[0], accounts[1]); + expect(await wallet.getOwners()).to.deep.eq([accounts[0], accounts[1]]); + }); + + it('cannot add members, when not admin', async () => { + await wallet.create(accounts[0], accounts[0], [accounts[0]]); + const promise = wallet.addOwner(accounts[1], accounts[1]); + await expect(promise).to.be.rejected; + }); + + it('can remove members, when admin', async () => { + await wallet.create(accounts[0], accounts[0], [accounts[0], accounts[1]]); + expect(await wallet.getOwners()).to.deep.eq([accounts[0], accounts[1]]); + await wallet.removeOwner(accounts[0], accounts[1]); + expect(await wallet.getOwners()).to.deep.eq([accounts[0]]); + }); + + it('cannot remove members, when not admin', async () => { + await wallet.create(accounts[0], accounts[0], [accounts[0], accounts[1]]); + const promise = wallet.removeOwner(accounts[1], accounts[1]); + await expect(promise).to.be.rejected; + }); + }); + + describe('when submitting transactions', () => { + it('can instantly submit transactions', async () => { + await wallet.create(accounts[0], accounts[0], [accounts[0], accounts[1]]); + + // create test contract and hand over to wallet + const testContract = await executor.createContract('Owned', [], { from: accounts[0], gas: 200000, }); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(accounts[0]); + await executor.executeContractTransaction(testContract, 'transferOwnership', { from: accounts[0], }, wallet.walletContract.options.address); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(wallet.walletContract.options.address); + + await wallet.submitTransaction(testContract, 'transferOwnership', { from: accounts[0], }, accounts[1]); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(accounts[1]); + + await executor.executeContractTransaction(testContract, 'transferOwnership', { from: accounts[1], }, wallet.walletContract.options.address); + + await wallet.submitTransaction(testContract, 'transferOwnership', { from: accounts[1], }, accounts[0]); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(accounts[0]); + }); + + it('cannot submit transactions, when not in owners group', async () => { + await wallet.create(accounts[0], accounts[0], [accounts[0]]); + + // create test contract and hand over to wallet + const testContract = await executor.createContract('Owned', [], { from: accounts[0], gas: 200000, }); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(accounts[0]); + await executor.executeContractTransaction(testContract, 'transferOwnership', { from: accounts[0], }, wallet.walletContract.options.address); + expect(await executor.executeContractCall(testContract, 'owner')).to.eq(wallet.walletContract.options.address); + + const promise = wallet.submitTransaction(testContract, 'transferOwnership', { from: accounts[1], }, accounts[1]); + await expect(promise).to.be.rejected; + }); + }); +}); diff --git a/src/contracts/wallet.ts b/src/contracts/wallet.ts new file mode 100644 index 00000000..399c36d9 --- /dev/null +++ b/src/contracts/wallet.ts @@ -0,0 +1,296 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ +*/ + +import coder = require('web3-eth-abi'); + +import { + ContractLoader, + Description, + EventHub, + Executor, + Logger, + LoggerOptions, + NameResolver, +} from '@evan.network/dbcp'; + + +export interface WalletOptions extends LoggerOptions { + contractLoader: ContractLoader; + description: Description; + eventHub: EventHub; + executor: Executor; + nameResolver: NameResolver; +} + +/** + * Wallet helper. Used to create and manage wallets + * + * @class Sharing (name) + */ +export class Wallet extends Logger { + options: WalletOptions; + defaultDescription: any = { + 'public': { + 'name': 'MultiSigWallet contract', + 'description': 'allows multiple accounts to aggree on transactions', + 'author': 'evan.network GmbH', + 'version': '0.0.1', + 'dbcpVersion': 1, + } + }; + receipts = {}; + walletContract: any; + + constructor(options: WalletOptions) { + super(options); + this.options = options; + this.defaultDescription.public.abis = { + own: JSON.parse(this.options.contractLoader.contracts.MultiSigWallet.interface), + }; + const that = this; + const signAndExecuteTransaction = this.options.executor.signer.signAndExecuteTransaction; + this.options.executor.signer.signAndExecuteTransaction = + function(contract, functionName, functionArguments, innerOptions, handleTxResult) { + signAndExecuteTransaction.call(that.options.executor.signer, contract, functionName, functionArguments, innerOptions, (error, receipt) => { + if (receipt) { + that.receipts[receipt.transactionHash] = receipt; + } + handleTxResult(error, receipt); + }); + }; + } + + /** + * add an owner to a wallet contract + * + * @param {string} accountId account with management permissions on wallet + * @param {string} toAdd account to add as an owner + * @return {Promise} resolved when done + */ + public async addOwner(accountId: string, toAdd: string): Promise { + await this.options.executor.executeContractTransaction( + this.ensureContract(), + 'addOwner', + { from: accountId, }, + toAdd + ); + } + + /** + * create a new wallet contract and uses it as its wallet contract + * + * @param {string} accountId account id, that creates the wallet + * @param {string} manager account, that will be able to manage the new wallet + * @param {string[]} owners wallet owners + * @return {Promise} resolved when done + */ + public async create(accountId: string, manager: string, owners: string[]): Promise { + // get factory + const factoryDomain = this.options.nameResolver.getDomainName( + this.options.nameResolver.config.domains.factory, + this.options.nameResolver.config.labels.wallet + ); + const factoryAddress = await this.options.nameResolver.getAddress(factoryDomain); + if (!factoryAddress) { + throw new Error(`factory '${factoryDomain}' for creating wallets not found in ` + + `'${this.options.nameResolver.config.labels.businessCenterRoot}'`); + } + const factory = this.options.contractLoader.loadContract('MultiSigWalletFactory', factoryAddress); + // create contract via factory + const contractId = await this.options.executor.executeContractTransaction( + factory, + 'createContract', { + from: accountId, + autoGas: 1.1, + event: { target: 'MultiSigWalletFactory', eventName: 'ContractCreated', }, + getEventResult: (event, args) => args.newAddress, + }, + manager, + owners, + 1, + ); + // add description + await this.options.description.setDescriptionToContract(contractId, this.defaultDescription, accountId); + + this.walletContract = this.options.contractLoader.loadContract('MultiSigWallet', contractId); + } + + /** + * get all owners of a wallet + * + * @return {string[]} wallet owners + */ + public async getOwners(): Promise { + return this.options.executor.executeContractCall(this.ensureContract(), 'getOwners'); + } + + /** + * load wallet contract from address + * + * @param {string} contractId a wallet contract address + * @return {void} + */ + public load(contractId: string): void { + this.walletContract = this.options.contractLoader.loadContract('MultiSigWallet', contractId); + } + + /** + * remove an owner from a wallet contract + * + * @param {string} accountId account with management permissions on wallet + * @param {string} toRemove account to remove from wallet owners + * @return {Promise} resolved when done + */ + public async removeOwner(accountId: string, toRemove: string): Promise { + await this.options.executor.executeContractTransaction( + this.ensureContract(), + 'removeOwner', + { from: accountId, }, + toRemove + ); + } + + /** + * submit a transaction to a wallet + * + * @param {any} target contract of the submitted transaction + * @param {string} functionName name of the contract function to call + * @param {any} inputOptions currently supported: from, gas, event, + * getEventResult, eventTimeout, estimate, force + * @param {any[]} functionArguments optional arguments to pass to contract + * transaction + * @return {Promise} status information about transaction + */ + public async submitTransaction(target: any, functionName: string, inputOptions: any, ...functionArguments): Promise { + const subscriptions = []; + let receipt; + try { + receipt = await new Promise(async (resolve, reject) => { + try { + let txResolved; + setTimeout(() => { + if (!txResolved) { + txResolved = true; + reject('wallet timeout'); + } + }, 600000); + + // serialize data + const encoded = this.encodeFunctionParams(functionName, target, functionArguments); + + // tx status variables + let transactionHash; + let walletTransactionId; + const transactionEvents = {}; + const transactionEventResults = {}; + + // helper functions + const resolveIfPossible = () => { + if (transactionHash && // from Submission event + walletTransactionId && // from Submission event + this.receipts[transactionHash] && // from signer receipt fetching + transactionEvents[walletTransactionId]) { // from Execution/ExecutionFailure + txResolved = true; + if (transactionEvents[walletTransactionId].event === 'ExecutionFailure') { + return reject('ExecutionFailure'); + } + resolve(this.receipts[transactionHash]); + } + }; + + // subscribe to events for status tracking + const walletInstance = this.ensureContract(); + // triggers on tx submission + // triggers on success + subscriptions.push(await this.options.eventHub.subscribe('MultiSigWallet', walletInstance.options.address, 'Execution', () => true, + (event) => { + this.log(`received MultiSigWallet Execution event with txid: ${event.returnValues.transactionId} ${event.transactionHash}`, 'debug'); + transactionEvents[event.returnValues.transactionId] = event; + resolveIfPossible(); + } + )); + // triggers on failure + subscriptions.push(await this.options.eventHub.subscribe('MultiSigWallet', walletInstance.options.address, 'ExecutionFailure', () => true, + (event) => { + this.log(`received MultiSigWallet ExecutionFailure event with txid: ${event.returnValues.transactionId} ${event.transactionHash}`, 'debug'); + transactionEvents[event.returnValues.transactionId] = event; + resolveIfPossible(); + } + )); + + // execute to contract + const options = Object.assign(JSON.parse(JSON.stringify(inputOptions)), { + event: { target: 'MultiSigWallet', eventName: 'Submission', }, + getEventResult: (event, args) => { + this.log(`received MultiSigWallet Submission event with hash: ${event.transactionHash} and txid: ${args.transactionId}`, 'debug'); + transactionHash = event.transactionHash; + walletTransactionId = args.transactionId; + resolveIfPossible(); + } + }); + await this.options.executor.executeContractTransaction( + walletInstance, + 'submitTransaction', + options, + target.options.address, + inputOptions.value || 0, + encoded, + ); + resolveIfPossible(); + } catch (ex) { + reject(ex); + } + }); + } catch (ex) { + throw new Error(ex.message || ex); + } finally { + // cleanup subscriptions + await Promise.all(subscriptions.map(s => this.options.eventHub.unsubscribe({ subscription: s }))); + } + + return receipt; + } + + private encodeFunctionParams(functionName: string, contractInstance: any, params: any[]) { + if (params.length) { + return contractInstance.options.jsonInterface + .filter(json => json.name === functionName && json.inputs.length === params.length) + .map(json => [ json.inputs.map(input => input.type), this.options.executor.web3.eth.abi.encodeFunctionSignature(json) ]) + .map(([types, signature]) => `${signature}${coder.encodeParameters(types, params).replace('0x', '')}`)[0] + ; + } else { + return '0x'; + } + } + + private ensureContract(): any { + if (!this.walletContract) { + throw new Error('no wallet contract specified at wallet helper, load or create one'); + } + return this.walletContract; + } +} diff --git a/src/dfs/ipld.spec.ts b/src/dfs/ipld.spec.ts index e1252c5e..2095d971 100644 --- a/src/dfs/ipld.spec.ts +++ b/src/dfs/ipld.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; diff --git a/src/dfs/ipld.ts b/src/dfs/ipld.ts index 467c0ed1..b0a752d1 100644 --- a/src/dfs/ipld.ts +++ b/src/dfs/ipld.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import Graph = require('ipld-graph-builder'); diff --git a/src/encryption/aes-blob.spec.ts b/src/encryption/aes-blob.spec.ts index 6e091a78..830db4a4 100644 --- a/src/encryption/aes-blob.spec.ts +++ b/src/encryption/aes-blob.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; diff --git a/src/encryption/aes-blob.ts b/src/encryption/aes-blob.ts index dcd821ef..167d3bb9 100644 --- a/src/encryption/aes-blob.ts +++ b/src/encryption/aes-blob.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import crypto = require('crypto-browserify'); diff --git a/src/encryption/aes-ecb.spec.ts b/src/encryption/aes-ecb.spec.ts index 36ae9b81..8f6b8f2e 100644 --- a/src/encryption/aes-ecb.spec.ts +++ b/src/encryption/aes-ecb.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; diff --git a/src/encryption/aes-ecb.ts b/src/encryption/aes-ecb.ts index b0b8bae0..aa8ca302 100644 --- a/src/encryption/aes-ecb.ts +++ b/src/encryption/aes-ecb.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import crypto = require('crypto-browserify'); diff --git a/src/encryption/aes.spec.ts b/src/encryption/aes.spec.ts index ed5a179a..929d56fa 100644 --- a/src/encryption/aes.spec.ts +++ b/src/encryption/aes.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; diff --git a/src/encryption/aes.ts b/src/encryption/aes.ts index 9db9f85e..a37f27db 100644 --- a/src/encryption/aes.ts +++ b/src/encryption/aes.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import crypto = require('crypto-browserify'); diff --git a/src/encryption/crypto-provider.ts b/src/encryption/crypto-provider.ts index 3001c78d..8b8fa48a 100644 --- a/src/encryption/crypto-provider.ts +++ b/src/encryption/crypto-provider.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import { diff --git a/src/index.ts b/src/index.ts index d117be60..6fa2a38d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ export { diff --git a/src/keyExchange.spec.ts b/src/keyExchange.spec.ts index d735c665..28ed7fd6 100644 --- a/src/keyExchange.spec.ts +++ b/src/keyExchange.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; diff --git a/src/keyExchange.ts b/src/keyExchange.ts index a17aa29c..e657b3e9 100644 --- a/src/keyExchange.ts +++ b/src/keyExchange.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import crypto = require('crypto-browserify'); diff --git a/src/mailbox.spec.ts b/src/mailbox.spec.ts index dfc2eb3e..a3d35ed9 100644 --- a/src/mailbox.spec.ts +++ b/src/mailbox.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; diff --git a/src/mailbox.ts b/src/mailbox.ts index c0f3ff68..7b9ae1ec 100644 --- a/src/mailbox.ts +++ b/src/mailbox.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import { @@ -115,7 +115,7 @@ export class Mailbox extends Logger { } else { const domain = this.nameResolver.getDomainName(this.nameResolver.config.domains.mailbox); const address = await this.nameResolver.getAddress(domain); - this.mailboxContract = this.contractLoader.loadContract('MailBox', address); + this.mailboxContract = this.contractLoader.loadContract('MailBoxInterface', address); this.initialized = true; } } diff --git a/src/onboarding.spec.ts b/src/onboarding.spec.ts index 3a89394b..5e2796f0 100644 --- a/src/onboarding.spec.ts +++ b/src/onboarding.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; diff --git a/src/onboarding.ts b/src/onboarding.ts index 39c426c5..23016e55 100644 --- a/src/onboarding.ts +++ b/src/onboarding.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import { diff --git a/src/profile/business-center-profile.spec.ts b/src/profile/business-center-profile.spec.ts index c3d374c5..05c8a29a 100644 --- a/src/profile/business-center-profile.spec.ts +++ b/src/profile/business-center-profile.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; diff --git a/src/profile/business-center-profile.ts b/src/profile/business-center-profile.ts index 75f34089..06258742 100644 --- a/src/profile/business-center-profile.ts +++ b/src/profile/business-center-profile.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import { diff --git a/src/profile/profile.spec.ts b/src/profile/profile.spec.ts index 4ff0e041..e52280fd 100644 --- a/src/profile/profile.spec.ts +++ b/src/profile/profile.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; @@ -210,7 +210,7 @@ describe('Profile helper', function() { it('should be able to set and load a value for a given users profile contract from the blockchain', async () => { const nameResolver = await TestUtils.getNameResolver(web3); const address = await nameResolver.getAddress(ensName); - const contract = nameResolver.contractLoader.loadContract('ProfileIndex', address); + const contract = nameResolver.contractLoader.loadContract('ProfileIndexInterface', address); const label = await nameResolver.sha3('profiles'); const valueToSet = '0x0000000000000000000000000000000000000004'; let hash; @@ -544,7 +544,7 @@ describe('Profile helper', function() { // stores profile (atm still done as receiver, as this is msg.sender relative) const profileIndexDomain = nameResolver.getDomainName(nameResolver.config.domains.profile); const address = await nameResolver.getAddress(profileIndexDomain); - const contract = nameResolver.contractLoader.loadContract('ProfileIndex', address); + const contract = nameResolver.contractLoader.loadContract('ProfileIndexInterface', address); await executor.executeContractTransaction( contract, 'setMyProfile', { from: profileReceiver, autoGas: 1.1, }, profileContract.options.address); // can read own keys diff --git a/src/profile/profile.ts b/src/profile/profile.ts index 4d1b3aa8..6cfb492f 100644 --- a/src/profile/profile.ts +++ b/src/profile/profile.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import { @@ -226,7 +226,7 @@ export class Profile extends Logger { (async () => { const ensName = this.nameResolver.getDomainName(this.nameResolver.config.domains.profile); const address = await this.nameResolver.getAddress(ensName); - const contract = this.nameResolver.contractLoader.loadContract('ProfileIndex', address); + const contract = this.nameResolver.contractLoader.loadContract('ProfileIndexInterface', address); await this.executor.executeContractTransaction( contract, 'setMyProfile', { from: this.activeAccount, autoGas: 1.1, }, this.profileContract.options.address); })(), @@ -249,7 +249,7 @@ export class Profile extends Logger { async exists(): Promise { const ensName = this.nameResolver.getDomainName(this.nameResolver.config.domains.profile); const address = await this.nameResolver.getAddress(ensName); - const indexContract = this.nameResolver.contractLoader.loadContract('ProfileIndex', address); + const indexContract = this.nameResolver.contractLoader.loadContract('ProfileIndexInterface', address); const profileContractAddress = await this.executor.executeContractCall( indexContract, 'getProfile', this.activeAccount, { from: this.activeAccount, }); return profileContractAddress !== '0x0000000000000000000000000000000000000000'; @@ -437,7 +437,7 @@ export class Profile extends Logger { if (!this.profileContract) { const ensName = this.nameResolver.getDomainName(this.nameResolver.config.domains.profile); const address = await this.nameResolver.getAddress(ensName); - const indexContract = this.nameResolver.contractLoader.loadContract('ProfileIndex', address); + const indexContract = this.nameResolver.contractLoader.loadContract('ProfileIndexInterface', address); const profileContractAddress = await this.executor.executeContractCall( indexContract, 'getProfile', this.activeAccount, { from: this.activeAccount, }); if (profileContractAddress === '0x0000000000000000000000000000000000000000') { diff --git a/src/runtime.ts b/src/runtime.ts index 580f5020..78f532d4 100644 --- a/src/runtime.ts +++ b/src/runtime.ts @@ -1,32 +1,31 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import smartContract = require('@evan.network/smart-contracts-core'); -import smartContractsAdmin = require('@evan.network/smart-contracts-admin'); import { AccountStore, @@ -99,8 +98,11 @@ export async function createDefaultRuntime(web3: any, dfs: DfsInterface, runtime // get default logger const log = (new Logger()).logFunction; // get/compile smart contracts - const solc = new smartContract.Solc({ config: { compileContracts: false, }, log, }); - await solc.ensureCompiled([smartContractsAdmin.getContractsPath()]); + // It is possible to load contracts from non-default locations + const solcCfg = { compileContracts: false, } + if (runtimeConfig.contractsLoadPath) solcCfg['destinationPath'] = runtimeConfig.contractsLoadPath + const solc = new smartContract.Solc({ config: solcCfg, log, }); + await solc.ensureCompiled(); const contracts = solc.getContracts(); // web3 contract interfaces diff --git a/src/shared-description.spec.ts b/src/shared-description.spec.ts index 7450f4de..f7df02ae 100644 --- a/src/shared-description.spec.ts +++ b/src/shared-description.spec.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import 'mocha'; diff --git a/src/shared-description.ts b/src/shared-description.ts index c3dfd1bb..fc2500b0 100644 --- a/src/shared-description.ts +++ b/src/shared-description.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import { Envelope } from '@evan.network/dbcp'; diff --git a/src/test/accounts.ts b/src/test/accounts.ts index 5f59739a..94829baf 100644 --- a/src/test/accounts.ts +++ b/src/test/accounts.ts @@ -1,28 +1,28 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ const accountMap = { diff --git a/src/test/test-utils.ts b/src/test/test-utils.ts index 2352f324..19359d34 100644 --- a/src/test/test-utils.ts +++ b/src/test/test-utils.ts @@ -1,33 +1,32 @@ /* - Copyright (C) 2018-present evan GmbH. - + Copyright (C) 2018-present evan GmbH. + This program is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License, version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with this program. - If not, see http://www.gnu.org/licenses/ or write to the - - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, 02110-1301 USA, - - or download the license from the following URL: https://evan.network/license/ - - You can be released from the requirements of the GNU Affero General Public License - by purchasing a commercial license. - Buying such a license is mandatory as soon as you use this software or parts of it - on other blockchains than evan.network. - - For more information, please contact evan GmbH at this address: https://evan.network/license/ + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ + + You can be released from the requirements of the GNU Affero General Public + License by purchasing a commercial license. + Buying such a license is mandatory as soon as you use this software or parts + of it on other blockchains than evan.network. + + For more information, please contact evan GmbH at this address: + https://evan.network/license/ */ import IpfsApi = require('ipfs-api'); import smartContract = require('@evan.network/smart-contracts-core'); -import smartContractsAdmin = require('@evan.network/smart-contracts-admin'); import Web3 = require('web3'); import { @@ -49,9 +48,11 @@ import { accounts } from './accounts'; import { Aes } from '../encryption/aes'; import { AesEcb } from '../encryption/aes-ecb'; import { BaseContract } from '../contracts/base-contract/base-contract'; +import { Claims } from '../claims/claims'; import { config } from './../config'; import { CryptoProvider } from '../encryption/crypto-provider'; import { DataContract } from '../contracts/data-contract/data-contract'; +import { ExecutorWallet } from '../contracts/executor-wallet'; import { Ipld } from '../dfs/ipld'; import { Profile } from '../profile/profile'; import { RightsAndRoles } from '../contracts/rights-and-roles'; @@ -59,6 +60,7 @@ import { ServiceContract } from '../contracts/service-contract/service-contract' import { setTimeout } from 'timers'; import { Description } from '../shared-description'; import { Sharing } from '../contracts/sharing'; +import { Wallet } from '../contracts/wallet'; export const publicMailBoxExchange = 'mailboxKeyExchange'; @@ -116,6 +118,15 @@ export class TestUtils { }); }; + static async getClaims(web3): Promise { + const executor = await TestUtils.getExecutor(web3); + return new Claims({ + contractLoader: await TestUtils.getContractLoader(web3), + executor, + nameResolver: await this.getNameResolver(web3), + }); + } + static getConfig(): any { return config; } @@ -133,7 +144,7 @@ export class TestUtils { log: Logger.getDefaultLog(), config: { compileContracts: false, }, }); - await solc.ensureCompiled([smartContractsAdmin.getContractsPath()]); + await solc.ensureCompiled(); return solc.getContracts(); } @@ -219,6 +230,25 @@ export class TestUtils { } } + static async getExecutorWallet(web3, wallet, dfsParam?: DfsInterface): Promise { + const contracts = await this.getContracts(); + const contractLoader = new ContractLoader({ + contracts, + web3, + }); + const accountStore = this.getAccountStore({}); + const signer = new SignerInternal({ + accountStore, + contractLoader, + config: {}, + web3, + }); + const executor = new ExecutorWallet({ config, signer, wallet, web3, }); + await executor.init({}); + + return executor; + } + static async getIpld(_ipfs?: Ipfs, _keyProvider?: KeyProvider): Promise { const cryptor = new Aes(); const key = await cryptor.generateKey(); @@ -343,6 +373,19 @@ export class TestUtils { }); } + static async getWallet(web3, dfsParam?: DfsInterface): Promise { + const dfs = dfsParam ? dfsParam : await TestUtils.getIpfs(); + const executor = await TestUtils.getExecutor(web3); + executor.eventHub = await TestUtils.getEventHub(web3); + return new Wallet({ + contractLoader: await TestUtils.getContractLoader(web3), + description: await TestUtils.getDescription(web3, dfs), + eventHub: executor.eventHub, + executor, + nameResolver: await TestUtils.getNameResolver(web3), + }); + } + static getWeb3(provider = web3Provider) { // connect to web3 return new Web3(new Web3.providers.WebsocketProvider(provider));