The repository contains a substrate parachain that can be connected to an arbitrary bank account which supports the EBICS banking interface (ISO20022). It synchronizes balances and transaction of a bank account with the solo chain using an off-chain-worker and zero-knowledge proofs. This worker also contains extrinsincs to trigger wire-transfers on the connected bank account.
Zero-Knowledge proofs are used to enable trustless atomic swap between FIAT and any ledger technology. The system is called Hyperfridge - the whitepaper is here.
Our runtime includes a pallet called fiat-ramps
that is responsible for synchronization of bank account state with the on-chain state
Fiat-ramps
is located inside /pallets
folder. It is an offchain-worker pallet that primarily does two activities:
- Poll EBICS service to get the latest bank statements, puts them in the queue
- Polls EBICS service for the ZK receipt of the queued statements until it is available
- Reads the receipt and verifies it
- Process burn requests registered in the local pallet storage and send
unpeg
request to EBICS API.
Burn request is a single request to burn, transfer funds from EBICS supporting bank account using extrinsics. Account submits a request to a chain and it is registered in the local storage. Offchain worker picks up the burn request and sends it to the EBICS service. If everything goes well, EBICS service confirms the transaction and includes it in the statement, thus finalizing the burn request. This is done because transactions in traditional banks are not instant and sometimes it takes days to finalize them.
First, complete the basic Rust setup instructions.
Use the following command to build the node without launching it:
cargo build --release
Note: the above code might take long to compile depending on your machine specs
You should have zombienet
installed, at least version 1.3.104
.
Compile the node:
cargo build --release
Then, since Hyperfridge is a parachain, it requires a local network which consists of a relay chain and Asset Hub for XCM compatibility. You will need a compiled polkadot
and polkadot-parachain
binaries. Check out polkadot-sdk
and:
Build polkadot
:
cd polkadot && cargo install --path . --locked --features fast-runtime
fast-runtime
feature is important, because otherwise you will have to wait a long time until parachains
start producing blocks.
And then polkadot-parachain
binary for Asset Hub
:
cargo build --release --locked -p polkadot-parachain-bin --bin polkadot-parachain
And now, you should point path to those binaries in ENV variables:
export POLKADOT_BIN=/path/to/polkadot
export ASSET_HUB_BIN=/path/to/polkadot-parachain
Finally:
zombienet spawn -p native zombienet.toml
The log will print Polkadot.js
links to all nodes.
Or you can run the node with consistent state without --tmp
flag.
To run unit tests and integration tests, execute the following command:
cargo test
This runs unit tests specific to the fiat-ramps
pallet and integration tests that test Hyperfridge parachain's AssetHub integration.
To run clippy
linter, execute the following command:
cargo clippy
Following test accounts are for Alice, Bob and Charlie, respectively.
{
"accounts" : [ {
"ownerName" : "Alice",
"iban" : "CH2108307000289537320",
"accountId": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"bic" : "HYPLCH22570",
"offeredAccountId" : "accountname1",
"nexusBankAccountId" : "CH2108307000289537320"
}, {
"ownerName" : "Bob",
"iban" : "CH1230116000289537312",
"accountId": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"bic" : "HYPLCH22572",
"offeredAccountId" : "accountname2",
"nexusBankAccountId" : "CH1230116000289537312"
}, {
"ownerName" : "Charlie",
"iban" : "CH2108307000289537313",
"accountId": "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y",
"bic" : "HYPLCH22573",
"offeredAccountId" : "accountname3",
"nexusBankAccountId" : "CH2108307000289537313"
} ]
}
Once the node template is running locally, you can connect it with Polkadot-JS Apps front-end to interact with your chain. Click here connecting the Apps to your local node template.
Now you will be able to open the block explorer and see transactions, events that have occured in the blockchain.
For example, you can take a look at chain storage of fiat-ramps
here
For the offchain worker to sign transactions, we need to insert authority keys into the chain. This can be done using RPC call author_insert_key
which is located in PolkadotJs Apps interface RPC calls section.
For testing puroposes, we can use this account:
key_type: ramp
suri: cup swing hill dinner pioneer mom stick steel sad raven oak practice
public_key: 5C555czPfaHgYhKhsRg2KNCLGCJ82jVsvweTHAnfvT83uy5T
You can set the new url for the ebics-service
via PolkadotJS interface. Follow this link to the Sudo
tab and choose FiatRamps.setApiUrl
extrinsic. Paste the new url for the API and click Submit transaction
. If everything is good, i.e you are the Sudo account and you have the necessary rights, you should see the transaction included in the block and offchain worker starts querying the new API.
First, install Docker and Docker Compose.
Then run the following command to start a single node development chain.
Run with image from DockerHub:
docker run -it -p 9944:9944 e36io/ebics-ocw:hyperfridge --dev --tmp --unsafe-rpc-external --rpc-cors=all --rpc-methods=unsafe -loffchain-worker
Build:
docker build -t ebics-ocw .
Run:
docker run -it -p 9944:9944 ebics-ocw:latest --dev --tmp --unsafe-rpc-external --rpc-cors=all --rpc-methods=unsafe -loffchain-worker
Build:
docker build --platform linux/x86_64 -t ebics-ocw .
Run:
docker run --platform=linux/x86_64 -it -p 9944:9944 ebics-ocw:latest --dev --tmp --unsafe-rpc-external --rpc-cors=all --rpc-methods=unsafe -loffchain-worker
This chain needs EBICS Java service, which is responsible for connecting to the bank account and providing an API for our offchain worker to interact with. By default it is connected to a remote EBICS service. If you want to use a local EBICS service, you can find the service here. Follow the instructions in the README to run the service.