Recently, we’ve joined the Waves Grants program to implement a user-friendly escrow service on top of Waves platform, using the platform’s smart contract capabilities and a UI in a form of a frontend-only web app that utilizes the public Waves API and Waves Keeper for transaction authorization.
The solution executes all relevant logic and stores all data client-side — this is a deliberate design choice to eliminate potential abuse and ensure that all users of the solution retain control of their funds. All interaction with the Waves blockchain is done either through Waves Keeper or public Waves API.
The solution can be used on both testnet and mainnet, depending on the network chosen in the user’s Waves Keeper client.
The application contains the following components and features:
The account script
An account script implemented in RIDE that acts as a 2-out-of-2 multisig between the sender and the receiver that holds the funds for a period of time (grace period, set on contract launch). It releases the funds from the sender to the receiver if one of the following happens:
- the receiver submits a special transaction to the blockchain that uses a verification code to unlock the funds; the hash of the verification code is stored on script deployment;
- the time set as grace period (currently 1000 blocks) elapses, and the receiver sends a simple transaction to claim the funds, with no additional verification.
Frontend-only web app
Although, the application is hosted on a server, the server only responds with the app content with all JS functionality bundled for on-client use. The web app allows to de the following:
- Allows the sender to generate a new escrow account, by funding a new address for necessary transaction fees, deploying the script and sending the transaction amount to the account;
- Allows the sender to copy the verification code (which is a hash of the contract private key) to clipboard and send it to the receiver so that they can unlock funds;
- Allows the receiver to add an existing escrow account to their tracker by address;
- Allows the receiver to enter the verification key received from the sender to unlock funds, or to spend funds regardless of the verification key if the grace period has ended.
The following guide is a walkthrough of users’ interaction with the app.
When the user starts their session, they are prompted to create a secret, which is essentially a password. The hash of the secret is used as an encryption key for user data and the double-hash of the secret is used as persistent storage identifier. To make the experience more familiar to ordinary users, they must first create a new secret, and only then use it.
The user starts at the “Sender” tab. There they can create a new escrow contract by pressing “New”.
In the escrow creation pop-up, the user will be prompted to enter the counterparty public key (currently, it is a public key, the address is only displayed alongside it) and the sum.
To instantiate the contract (in three steps: pre-filling the address to pay fees, deploying the account data and deploying the script), the user presses the “Deploy” button. Waves Keeper will ask the user to authorize the fee transaction.
To fill the account with funds, the user presses “Fund” and authorizes the transaction in Keeper. After the transaction is mined, a new row for the created escrow will appear in the tracker.
From here, the user can check the escrow account in the explorer, track its status, and copy the verification key to clipboard with the key button.
In the recipient tab, the user can add the new escrow contract by its address.
The app will display the contract data and warn the user if their current selected address in Keeper does not match the recipient in the contract.
The recipient can then unlock the funds by pressing the unlock button and entering the verification key received from the sender on another channel. The app will notify the recipient if the verification key is correct/incorrect.
By pressing “Withdraw” and authorizing with the Keeper the recipient can spend the funds to their current address.
The currently available demo of the project can be accessed here.
The source code can be retrieved from the following Gitlab repository. To run a local version of the app, one has to clone the repository and follow the Readme instructions.
The code can be reused in other solutions as per the MIT License — the primary business logic is contained in blockchainUtils.js as a BlockchainConnector class that takes an instantiated Keeper API as a constructor parameter, although dependence bundling (such as with Webpack) is required to run on the browser. Note that most methods in blockchainUtils.js return Promises.
The rest of the source code constitutes various React components. The escrow script is presented as source for reference, but a pre-compiled base64 version is used in blockchainUtils.js.
Although the current implementation is fully functional and can be used for manual processing of transactions, there are still some quality of life and functional improvements to be done.
There are three major updates planned in the future:
- The first one is a natural extension of the escrow system towards allowing the participation of a selected arbiter.
- The second one is Waves Sonar, a general developer tool for Waves that allows subscription to arbitrary events on the Waves blockchain.
- The last one is an extension of the arbitrable escrow service that leverages the power of Waves Sonar to provide a wider scope of functionality with regards to operational contexts of escrow service integrations. Using Sonar would allow real time updates of the contract list by tracking all new contracts on the current address, an API for programmatic integration with existing services, and more.
Escrow contracts with arbiters
The service extends the present proposal with adding a new kind of agent into the product cycle: the arbiter. Arbiter’s address is also included in the escrow contract, which is now represented by a timed (or not timed, per user choice) 2-out-of-3 multisig: if there is a dispute, the arbiter can make a ruling towards either the buyer or the seller, instantly transferring the money to the selected party.
The solution for tracking the escrow addresses without user interaction (i.e. without the recipient adding the contract by address explicitly) is not included in this update, as it relies on Waves Sonar for its implementation.
Waves Sonar is a service that implements a developer tool similar in purpose to Ethereum Events. The Sonar service contains a mapping of listeners to callbacks. Each listener is a filter on transactions in a block. Once a new block is received by a full Waves node, listeners are applied to the transactions inside: if there are any transactions that pass the filter, a corresponding callback gets triggered with these transactions as input.
The following schematic describes the operation of the Sonar service in the context of the proposed solution:
While currently the solution is fully functional without the Sonar service, we believe its introduction would greatly boost the UX and the usability scope of the solution, and it also may be spun off into a standalone tool for Waves Dapp developers.
Integratable escrow for B2C/C2C services
This service relies on Waves Sonar as its prerequisite. It extends the functionality of the first Escrow proposal towards an integratable full-cycle version with three types of agents:
- “Buyers” (users that send the money and expect an out-of-Waves-chain product or service delivery);
- “Sellers” (users that receive the money for providing goods or services outside of Waves platform);
- “Arbiters” (users or platform support staff that are mentioned by buyers and/or sellers in the escrow contracts and are supposed to resolve disputes either way).
Such a service monitors the Waves Blockchain for events related to the escrow contracts and a particular user and notifies the user that a contract she has been marked as an arbiter for has entered dispute resolution state. This additionally allows to create a generic API for existing service integration.