Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented first draft of usdt integration #161

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.DS_Store
23 changes: 22 additions & 1 deletion modules/gateways/blockonomics.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ function () {
element.max = 10;
element.step = 0.01;
});

/**
* Generate Settings and Currency Headers
*/
Expand Down Expand Up @@ -393,6 +393,27 @@ function doTest() {
$settings_array[$code . 'Enabled']['Default'] = true;
}
}
$settings_array['UsdtAddress'] = [
'FriendlyName' => $_BLOCKLANG['usdtAddress']['title'],
'Description' => $_BLOCKLANG['usdtAddress']['description'],
'Type' => 'text',
];
$settings_array['EtherScanAPIKey'] = [
'FriendlyName' => $_BLOCKLANG['etherScanAPI']['title'],
'Description' => $_BLOCKLANG['etherScanAPI']['description'],
'Type' => 'text',
];
$settings_array['NetworkType'] = [
'FriendlyName' => $_BLOCKLANG['networkType']['title'],
'Description' => $_BLOCKLANG['networkType']['description'],
'Type' => 'dropdown',
'Default' => 'ethereum',
'Options' => [
'ethereum' => 'Main Ethereum Network',
'sepolia' => 'Sepolia Test Network',
]
];

return $settings_array;
}

Expand Down
7 changes: 5 additions & 2 deletions modules/gateways/blockonomics/assets/css/order.css
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ svg {
.bnomics-icon-btc:before {
content: "\e901";
}
.bnomics-icon-usdt:before {
content: "\e902";
}

.bnomics-select-options {
cursor:pointer;
Expand Down Expand Up @@ -339,13 +342,13 @@ svg {
margin-right: auto;
}

.bnomics-copy-container {
.bnomics-copy-container, .bnomics-checkout-container {
display:flex;
align-items: center;
position: relative;
}

.bnomics-copy-container input {
.bnomics-copy-container input, .bnomics-checkout-container input {
flex-grow: 1;
}

Expand Down
Binary file modified modules/gateways/blockonomics/assets/fonts/cryptos.woff
100755 → 100644
Binary file not shown.
Binary file added modules/gateways/blockonomics/assets/img/usdt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

Large diffs are not rendered by default.

265 changes: 265 additions & 0 deletions modules/gateways/blockonomics/assets/js/web3_checkout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
'use strict';
class Blockonomics {
constructor({ checkout_id = 'blockonomics_checkout' } = {}) {
// User Params
this.checkout_id = checkout_id;

// Initialise
this.init();
}

usdt = {
address: '',
abi: [
"function name() view returns (string)",
ashthecoder05 marked this conversation as resolved.
Show resolved Hide resolved
"function symbol() view returns (string)",
"function gimmeSome() external",
"function balanceOf(address _owner) public view returns (uint256 balance)",
"function transfer(address _to, uint256 _value) public returns (bool success)",
],
}

provider = null;
connectedAccount = null;

init() {
this.container = document.getElementById(this.checkout_id);
if (!this.container) {
throw Error(
`Blockonomics Initialisation Error: Container #${this.checkout_id} was not found!`
);
}

// Load data attributes
// This assumes a constant/var `blockonomics_data` is defined before the script is called.
try {
this.data = JSON.parse(blockonomics_data);
} catch (e) {
if (e.toString().includes('ReferenceError')) {
throw Error(
`Blockonomics Initialisation Error: Data Object was not found in Window. Please set blockonomics_data variable.`
);
}
throw Error(
`Blockonomics Initialisation Error: Data Object is not a valid JSON.`
);
}

this.create_bindings();

this._spinner_wrapper.style.display = 'none';
this._order_panel.style.display = 'block';

// Hide Display Error
this._display_error_wrapper.style.display = 'none';
this.wallet();
}

async wallet() {
const walletSetupTable = document.getElementById('wallet-setup-table');
const connectBtn = document.getElementById('connect-wallet');
const transferForm = document.getElementById('transferForm');
this.usdt.address = this.data.contract_address;

this.provider = new ethers.providers.Web3Provider(window.ethereum, "any");

this.provider.provider.on('accountsChanged', async () => {
this.checkConnection();
});

this.provider.on("network", (newNetwork, oldNetwork) => {
// When a Provider makes its initial connection, it emits a "network"
// event with a null oldNetwork along with the newNetwork. So, if the
// oldNetwork exists, it represents a changing network
if (oldNetwork) {
window.location.reload();
}
});

connectBtn.addEventListener('click', async () => {
await this.provider.send("eth_requestAccounts", []);
const signer = this.provider.getSigner();
this.connectedAccount = await signer.getAddress();
});

transferForm.addEventListener('submit', (e) => {
e.preventDefault();
this.transferusdt();
});


this.checkConnection();
}

async checkConnection() {
const walletSetupTable = document.getElementById('wallet-setup-table');
const walletInfoTable = document.getElementById('wallet-info');

try {
const signer = this.provider.getSigner();
const userAddress = await signer.getAddress();

const network = await this.provider.getNetwork();
document.getElementById("connectResponse").style.display = "none";
if(network.chainId !== Number(this.data.chain_id)) {
const response = `Please change the wallet network before connecting the wallet`;
document.getElementById("connectResponse").innerText = response;
document.getElementById("connectResponse").style.display = "block";
return;
}

if (userAddress) {
walletSetupTable.style.display = 'none';
walletInfoTable.style.display = 'table';

document.getElementById("userAddress").innerText = userAddress;

const usdtBalance = await this.getBalance(userAddress);
document.getElementById("userAmount").innerText = `${this.data.order_amount} USDT`;

const amount = ethers.utils.parseUnits(this.data.order_amount, this.data.crypto.decimals);

if (usdtBalance.lt(amount)) {
let amountFormatted = ethers.utils.formatUnits(amount, this.data.crypto.decimals);
let balanceFormatted = ethers.utils.formatUnits(usdtBalance, this.data.crypto.decimals);
console.error(
ashthecoder05 marked this conversation as resolved.
Show resolved Hide resolved
`Insufficient balance receiver send ${amountFormatted} (You have ${balanceFormatted})`
);

const response = `Insufficient balance receiver send ${amountFormatted} (You have ${balanceFormatted})`;
ashthecoder05 marked this conversation as resolved.
Show resolved Hide resolved
document.getElementById("transferResponse").innerText = response;
document.getElementById("transferResponse").style.display = "block";
}
} else {
walletSetupTable.style.display = 'table';
walletInfoTable.style.display = 'none';
}
} catch (e) {
console.log(e);
walletSetupTable.style.display = 'table';
walletInfoTable.style.display = 'none';
}
}

async getBalance(wallet) {
const signer = this.provider.getSigner();
const usdtContract = new ethers.Contract(this.usdt.address, this.usdt.abi, signer);
const balance = await usdtContract.balanceOf(wallet);
return balance;
// return ethers.utils.formatUnits(balance, 6);
}

async transferusdt() {
let receiver = this.data.usdt_receivers_address;

const signer = this.provider.getSigner();
const usdtContract = new ethers.Contract(this.usdt.address, this.usdt.abi, signer);
let response = '';
let amount = this.data.order_amount;

try {
receiver = ethers.utils.getAddress(receiver);
} catch {
response = `Invalid address: ${receiver}`;
document.getElementById("transferResponse").innerText = response;
document.getElementById("transferResponse").style.display = "block";
return;
}

try {
amount = ethers.utils.parseUnits(amount, 6);
ashthecoder05 marked this conversation as resolved.
Show resolved Hide resolved
if (amount.isNegative()) {
throw new Error();
}
} catch {
console.error(`Invalid amount: ${amount}`);
response = `Invalid amount: ${amount}`;
document.getElementById("transferResponse").innerText = response;
document.getElementById("transferResponse").style.display = "block";
return;
}

const userAddress = await signer.getAddress();
const balance = await usdtContract.balanceOf(userAddress);

if (balance.lt(amount)) {
let amountFormatted = ethers.utils.formatUnits(amount, 6);
let balanceFormatted = ethers.utils.formatUnits(balance, 6);
console.error(
`Insufficient balance receiver send ${amountFormatted} (You have ${balanceFormatted})`
);

response = `Insufficient balance receiver send ${amountFormatted} (You have ${balanceFormatted})`;
ashthecoder05 marked this conversation as resolved.
Show resolved Hide resolved
document.getElementById("transferResponse").innerText = response;
document.getElementById("transferResponse").style.display = "block";
return;
}

let amountFormatted = ethers.utils.formatUnits(amount, 6);

response = `Transferring ${amountFormatted} usdt receiver ${receiver.slice(
0,
6
)}...`;

document.getElementById("transferResponse").innerText = response;
document.getElementById("transferResponse").style.display = "block";

const gasPrice = await this.provider.getGasPrice();

const tx = await usdtContract.transfer(receiver, amount, { gasPrice });
document.getElementById(
ashthecoder05 marked this conversation as resolved.
Show resolved Hide resolved
"transferResponse"
).innerText += `Transaction hash: ${tx.hash}`;

const result = {
txn: tx.hash,
crypto: 'usdt'
};

console.log({tx});
ashthecoder05 marked this conversation as resolved.
Show resolved Hide resolved

this.redirect_to_finish_order(result);
}

async disconnect() {
await window.ethereum.request({
method: "eth_requestAccounts",
params: [{eth_accounts: {}}]
})
}

create_bindings() {
this._spinner_wrapper = this.container.querySelector(
'.bnomics-spinner-wrapper'
);

this._order_panel = this.container.querySelector(
'.bnomics-order-panel'
);

this._display_error_wrapper = this.container.querySelector(
'.bnomics-display-error'
);
}

redirect_to_finish_order(params = {}) {
let url = this.data.finish_order_url;

let queryParams = new URLSearchParams();
for (const key in params) {
if (params.hasOwnProperty(key)) {
queryParams.append(key, params[key]);
}
}

if (Array.from(queryParams).length > 0) {
url += '&' + queryParams.toString();
}

window.location.href = url;
}
}

// Automatically trigger only after DOM is loaded
new Blockonomics();
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,4 @@ var blockonomics_data = JSON.stringify({

<script type="text/javascript" src="{$WEB_ROOT}/modules/gateways/blockonomics/assets/js/vendors/reconnecting-websocket.min.js"></script>
<script type="text/javascript" src="{$WEB_ROOT}/modules/gateways/blockonomics/assets/js/vendors/qrious.min.js"></script>
<script type="text/javascript" src="{$WEB_ROOT}/modules/gateways/blockonomics/assets/js/checkout.js "></script>
<script type="text/javascript" src="{$WEB_ROOT}/modules/gateways/blockonomics/assets/js/checkout.js"></script>
Loading