Introduction

With this tool a merchant can accept payments through a smart contract using liquidity pools. Smart contract for merchant creates 0xProcessing.

Web3 processing allows clients to pay with Web3 wallets in any of the available iterations: either with a widget on the website or a mobile wallet.

In this case, the size of the liquidity pool, the number of transactions and their volume, as well as any other necessary information that you would like to broadcast, can be available to users in real time through the blockchain browser or frontend of your website.

In addition, the functionality of Web3 processing allows you to set up automatic payouts to your employees' Web3 wallets.

Before you start integrating the method, leave a support request to activate the appropriate functionality. This deposit method supports BNB chains.

First, you need to contact technical support to connect your merchant to this feature. After receiving an answer from technical support about readiness, you can start the integration.

API endpoint: https://web30.0xprocessing.com/

Check Web3 pool API for more details

To authorize in the API you need to generate a token in your personal account under "Settings - Merchant Management - Web3 API Token".

Requests must contain the APIKEY header with your API key.

The process of adding tokens to the whitelist

In order for the liquidity pool to accept the tokens you want, you must add them to the whitelist of the smart contract.

First, you need to select from the available tokens the ones you need to work with.

You can see the list of supported tokens in the method Info/SupportedTokens.

You can add tokens in the method ContractSettings/AddTokenToWhitelist.

All methods of interaction with the contract return the id of the request, the status of which can be viewed in the method Queue/Status/{requestId}

After executing the request, be sure to verify that the request has been successfully executed.

Depositing tokens into the pool by users

To deposit a token into the pool, you must create a "Deposit" button in the user environment.

Example: token_contract_address – token contract address (can be obtained from the method Info/SupportedTokens) pool_contract_address – address of the pool contract (can be obtained from the method Info/Contract)

HTML:

<button id="0xWeb3PoolConnectButton">Connect MetaMask</button>
<div id="0xWeb3PoolDepositSection" style="display: none">
<input type="number" min="0" step="any" id="0xWeb3PoolDepositInput" placeholder="Amount" />
<button data-token="{token_contract_address}" data-pool="{pool_contract_address}" id="0xWeb3PoolDepositButton">Deposit</button>
</div>

JS:


<script src="https://cdnjs.cloudflare.com/ajax/libs/web3/1.7.0-rc.0/web3.min.js"></script>
<script>
//Connect Metamask
    window.addEventListener('load',
    async () => {
    if (window.ethereum) {
    window.web3 = new window.Web3(window.ethereum);
    initConnectButton();
    } else if (window.web3) {
    window.web3 = new Web3(window.web3.currentProvider);
    initConnectButton();
    }
    });

    //Initializing the connection button
    const initConnectButton = async () => {
                                web3.eth.getAccounts(function(err, accounts) {
                                    if (err != null) {
                                        document.getElementById('0xWeb3PoolConnectButton').style.display = 'none';
                                    }
                                });

                                document.getElementById('0xWeb3PoolConnectButton').addEventListener('click',
                                    async () => {
                                        if (window.ethereum) {
                                            try {
                                                await window.ethereum.request({ method: 'eth_requestAccounts' });
                                                initPayButton();
                                            } catch (err) {
                                                console.log('User denied access', err);
                                            }
                                        } else if (window.web3) {
                                            window.web3 = new Web3(window.web3.currentProvider);
                                            initPayButton();
                                        }
                                    });
                            }

                            //Initialization of the payment button
                            const initPayButton = () => {
                                document.getElementById('0xWeb3PoolConnectButton').style.display = 'none';
                                document.getElementById('0xWeb3PoolDepositSection').style.display = 'block';

                                document.getElementById('0xWeb3PoolDepositButton').addEventListener('click',
                                    async () => {
                                        var accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
                                        web3.eth.defaultAccount = accounts[0];

                                        const contractAbi = JSON.parse('[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"_decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]');

                                        //Token contract address
                                        var tokenAddress = document.getElementById('0xWeb3PoolDepositButton').dataset.token;
                                        //Obtaining the object of the contract
                                        const contract = new web3.eth.Contract(contractAbi, tokenAddress);
                                        //Address of the pool for the deposit
                                        var to = document.getElementById('0xWeb3PoolDepositButton').dataset.pool;
                                        //Deposit amount
                                        var amount = document.getElementById('0xWeb3PoolDepositInput').value;
                                        const decimals = web3.utils.toBN(18);
                                        var value = amount * Math.pow(10, decimals);

                                        //Calling the transfer contract method
                                        contract.methods.transfer(to, web3.utils.toHex(value)).send({ from: accounts[0] },
                                            function(error, result) {
                                                if (!error) {
                                                    //Transaction result processing
                                                    console.log(result);
                                                } else {
                                                    //Transaction error processing
                                                    console.log(error);
                                                }
                                            });
                                    });
                            }
                        </script>

Webhook

All deposits are tracked by the system and you can get a callback on a user's successful deposit into the pool.

The report of the deposit is implemented by means of webhooks.

You need to configure the webhook in your Merchant’s account in the section "Merchant\ Web3 processing\Webhook URL". Required https (TLS/SSL)

WebHook password - password required to check the signature.

Parameters:

Name
Description
Type

Id

Transaction Id

integer

From

Sender's address

string

To

Recipient's address

string

Amount

Amount

double

Currency

Currency

string

Hash

Transaction Hash

string

Type

Transaction type: claim, deposit, withdraw

string

Signature

Checksum, to verify the authenticity of the request

string

Signature Check:

1. A string of the following form must be generated: "Id":"Currency":"Hash":"From":"Password" (Without quotation marks through a colon)

2. Encrypt the resulting string using the MD5 algorithm

https://emn178.github.io/online-tools/md5.html

3. Compare the resulting string with the one that came through Webhook

4. If the strings match, you should return HTTP Status 200 (Required)

Example Webhook JSON:

                        {
                        "Id":19851,
                        "From":"0x000000.....",
                        "To":"0x000000.....",
                        "Amount":10.00264765,
                        "Currency":"BNB",
                        "Hash":"0x000000.....",
                        "Type": "claim",
                        "Signature":"a5510c8c3e657ffd8229813749cd20ec"
                        }

Claim

To allow a user to claim tokens from the pool (withdrawal), it is necessary to reserve an amount for that user in the contract, as well as provide the user with a Claim button.

To reserve the required amount for a certain user, you need to call the method Claim/AddUserClaimable.

During the reservation, the commission of the pool will be withdrawn.You can find this information on the form Info/Contract.

After successfully reserving an amount, the user can "claim" it from the contract via claim.

In order for the user to pick up his tokens, it is necessary to call the method Claim of the contract.

Example button: HTML:

                        <div id="0xWeb3PoolClaimSection" style="display: none">
                            <p>Available: <span id="0xWeb3PoolClaimAvailable"></span></p>
                            <input type="number" min="0" step="any" id="0xWeb3PoolClaimInput" placeholder="Amount" />
                            <button data-token="{token_contract_address}" data-pool="{pool_contract_address}" id="0xWeb3PoolClaimButton">Claim</button>
                        </div>

JS:

                        <script src="https://cdnjs.cloudflare.com/ajax/libs/web3/1.7.0-rc.0/web3.min.js"></script>
                        <script>
                            window.addEventListener('load',
                                // Connecting Metamask
                                async () => {
                                    if (window.ethereum) {
                                        window.web3 = new window.Web3(window.ethereum);
                                        initConnectButton();
                                    } else if (window.web3) {
                                        window.web3 = new Web3(window.web3.currentProvider);
                                        initConnectButton();
                                    }
                                });


                            const initConnectButton = async () => {
                                web3.eth.getAccounts(function(err, accounts) {
                                    if (err != null) {
                                        document.getElementById('0xWeb3PoolConnectButton').style.display = 'none';
                                    }
                                });

                                document.getElementById('0xWeb3PoolConnectButton').addEventListener('click',
                                    async () => {
                                        if (window.ethereum) {
                                            try {
                                                await window.ethereum.request({ method: 'eth_requestAccounts' });
                                                    initClaimButton();
                                            } catch (err) {
                                                console.log('User denied access', err);
                                            }
                                        } else if (window.web3) {
                                            window.web3 = new Web3(window.web3.currentProvider);
                                                initClaimButton();
                                        }
                                    });
                            }

                            const initClaimButton = async () => {
                                document.getElementById('0xWeb3PoolConnectButton').style.display = 'none';
                                document.getElementById('0xWeb3PoolClaimSection').style.display = 'block';

                                const contractAbi = JSON.parse('[{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"inputs":[{"internalType":"address","name":"recepient","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"addUserClaimable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"claimFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"claimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPercent","type":"uint256"}],"name":"feePercentChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeRecepient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recepient","type":"address"}],"name":"feeRecepientChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"reserved","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"whitelistERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistedERC20","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recepient","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawalAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"}]');

                                var accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
                                web3.eth.defaultAccount = accounts[0];

                                var tokenAddress =  document.getElementById('0xWeb3PoolClaimButton').dataset.token;
                                var poolAddress = document.getElementById('0xWeb3PoolClaimButton').dataset.pool;
                                var contract = new web3.eth.Contract(contractAbi, poolAddress);
                                var decimals = web3.utils.toBN(18);

                                contract.methods.claimable(accounts[0], tokenAddress).call(function(error, result) {
                                    document.getElementById('0xWeb3PoolClaimAvailable').innerHTML = result / Math.pow(10, decimals);
                                });

                                document.getElementById('0xWeb3PoolClaimButton').addEventListener('click',
                                    async () => {
                                        var amount = document.getElementById('0xWeb3PoolClaimInput').value;
                                        var value = amount * Math.pow(10, decimals);

                                        console.log(value);

                                        contract.methods.claim(web3.utils.toHex(value), tokenAddress).send({ from: accounts[0] },
                                            function (error, result) {
                                                if (!error) {
                                                    console.log(result);
                                                } else {
                                                    console.log(error);
                                                }
                                            });
                                    });
                            }
                        </script>

The result of the claim procedure, that is, when the user received tokens from the contract to his wallet can be received in the same way as a deposit.

Withdraw

Withdraw the balance of tokens from the contract (except those reserved for users).

Withdrawal of free tokens is performed using the method /Withdraw

The number of available free tokens can be obtained by the method /Contract/Info

Last updated