Browse Source

Add ETHO and ETI wallet payment support

main
def 6 days ago
parent
commit
19531c68c6
  1. 41
      backend/app.py
  2. 36
      templates/portal_invoice_detail.html

41
backend/app.py

@ -60,6 +60,11 @@ RPC_ARBITRUM_URL = os.getenv("OTB_BILLING_RPC_ARBITRUM", "https://arbitrum-one-r
RPC_ARBITRUM_URL_2 = os.getenv("OTB_BILLING_RPC_ARBITRUM_2", "https://rpc.ankr.com/arbitrum") RPC_ARBITRUM_URL_2 = os.getenv("OTB_BILLING_RPC_ARBITRUM_2", "https://rpc.ankr.com/arbitrum")
RPC_ARBITRUM_URL_3 = os.getenv("OTB_BILLING_RPC_ARBITRUM_3", "https://arb1.arbitrum.io/rpc") RPC_ARBITRUM_URL_3 = os.getenv("OTB_BILLING_RPC_ARBITRUM_3", "https://arb1.arbitrum.io/rpc")
RPC_ETICA_URL = os.getenv("OTB_BILLING_RPC_ETICA", "https://rpc.etica-stats.org")
RPC_ETICA_URL_2 = os.getenv("OTB_BILLING_RPC_ETICA_2", "https://eticamainnet.eticaprotocol.org")
RPC_ETHO_URL = os.getenv("OTB_BILLING_RPC_ETHO", "https://rpc.ethoprotocol.com")
RPC_ETHO_URL_2 = os.getenv("OTB_BILLING_RPC_ETHO_2", "https://rpc4.ethoprotocol.com")
CRYPTO_PROCESSING_TIMEOUT_SECONDS = int(os.getenv("OTB_BILLING_CRYPTO_PROCESSING_TIMEOUT_SECONDS", "180")) CRYPTO_PROCESSING_TIMEOUT_SECONDS = int(os.getenv("OTB_BILLING_CRYPTO_PROCESSING_TIMEOUT_SECONDS", "180"))
CRYPTO_WATCH_INTERVAL_SECONDS = int(os.getenv("OTB_BILLING_CRYPTO_WATCH_INTERVAL_SECONDS", "30")) CRYPTO_WATCH_INTERVAL_SECONDS = int(os.getenv("OTB_BILLING_CRYPTO_WATCH_INTERVAL_SECONDS", "30"))
CRYPTO_WATCHER_STARTED = False CRYPTO_WATCHER_STARTED = False
@ -230,11 +235,23 @@ def get_invoice_crypto_options(invoice):
"label": "ETHO (Etho)", "label": "ETHO (Etho)",
"payment_currency": "ETHO", "payment_currency": "ETHO",
"wallet_address": CRYPTO_EVM_PAYMENT_ADDRESS, "wallet_address": CRYPTO_EVM_PAYMENT_ADDRESS,
"wallet_capable": False, "wallet_capable": True,
"asset_type": "native", "asset_type": "native",
"chain_id": None, "chain_id": 1313114,
"decimals": 18, "decimals": 18,
"token_contract": None, "token_contract": None,
"rpc_urls": [RPC_ETHO_URL, RPC_ETHO_URL_2],
"chain_add_params": {
"chainId": "0x14095a",
"chainName": "Etho Protocol",
"nativeCurrency": {
"name": "Etho Protocol",
"symbol": "ETHO",
"decimals": 18
},
"rpcUrls": [RPC_ETHO_URL, RPC_ETHO_URL_2],
"blockExplorerUrls": ["https://explorer.ethoprotocol.com"]
},
}, },
"ETI": { "ETI": {
"symbol": "ETI", "symbol": "ETI",
@ -242,11 +259,23 @@ def get_invoice_crypto_options(invoice):
"label": "ETI (Etica)", "label": "ETI (Etica)",
"payment_currency": "ETI", "payment_currency": "ETI",
"wallet_address": CRYPTO_EVM_PAYMENT_ADDRESS, "wallet_address": CRYPTO_EVM_PAYMENT_ADDRESS,
"wallet_capable": False, "wallet_capable": True,
"asset_type": "token", "asset_type": "token",
"chain_id": None, "chain_id": 61803,
"decimals": 18, "decimals": 18,
"token_contract": "0x34c61EA91bAcdA647269d4e310A86b875c09946f", "token_contract": "0x34c61EA91bAcdA647269d4e310A86b875c09946f",
"rpc_urls": [RPC_ETICA_URL, RPC_ETICA_URL_2],
"chain_add_params": {
"chainId": "0xf16b",
"chainName": "Etica",
"nativeCurrency": {
"name": "Etica Gas",
"symbol": "EGAZ",
"decimals": 18
},
"rpcUrls": [RPC_ETICA_URL, RPC_ETICA_URL_2],
"blockExplorerUrls": ["https://explorer.etica-stats.org"]
},
}, },
} }
@ -276,6 +305,10 @@ def get_rpc_urls_for_chain(chain_name):
return [u for u in [RPC_ETHEREUM_URL, RPC_ETHEREUM_URL_2, RPC_ETHEREUM_URL_3] if u] return [u for u in [RPC_ETHEREUM_URL, RPC_ETHEREUM_URL_2, RPC_ETHEREUM_URL_3] if u]
if chain == "arbitrum": if chain == "arbitrum":
return [u for u in [RPC_ARBITRUM_URL, RPC_ARBITRUM_URL_2, RPC_ARBITRUM_URL_3] if u] return [u for u in [RPC_ARBITRUM_URL, RPC_ARBITRUM_URL_2, RPC_ARBITRUM_URL_3] if u]
if chain == "etica":
return [u for u in [RPC_ETICA_URL, RPC_ETICA_URL_2] if u]
if chain == "etho":
return [u for u in [RPC_ETHO_URL, RPC_ETHO_URL_2] if u]
return [] return []
def rpc_call_any(rpc_urls, method, params): def rpc_call_any(rpc_urls, method, params):

36
templates/portal_invoice_detail.html

@ -262,6 +262,7 @@
data-amount="{{ pending_crypto_payment.payment_amount }}" data-amount="{{ pending_crypto_payment.payment_amount }}"
data-decimals="{{ selected_crypto_option.decimals }}" data-decimals="{{ selected_crypto_option.decimals }}"
data-token-contract="{{ selected_crypto_option.token_contract or '' }}" data-token-contract="{{ selected_crypto_option.token_contract or '' }}"
data-chain-add='{{ (selected_crypto_option.chain_add_params or {})|tojson|safe }}'
> >
Open MetaMask / Rabby Open MetaMask / Rabby
</button> </button>
@ -441,12 +442,29 @@
return "0x" + method + addr + amtHex; return "0x" + method + addr + amtHex;
} }
async function switchChain(chainId) { async function switchChain(chainId, chainAddParams) {
const hexChainId = "0x" + Number(chainId).toString(16); const hexChainId = "0x" + Number(chainId).toString(16);
await window.ethereum.request({ try {
method: "wallet_switchEthereumChain", await window.ethereum.request({
params: [{ chainId: hexChainId }] method: "wallet_switchEthereumChain",
}); params: [{ chainId: hexChainId }]
});
return;
} catch (err) {
const code = err && (err.code ?? err?.data?.originalError?.code);
if ((code === 4902 || String(err).includes("4902")) && chainAddParams) {
await window.ethereum.request({
method: "wallet_addEthereumChain",
params: [chainAddParams]
});
await window.ethereum.request({
method: "wallet_switchEthereumChain",
params: [{ chainId: hexChainId }]
});
return;
}
throw err;
}
} }
function buildMetaMaskMobileLink() { function buildMetaMaskMobileLink() {
@ -571,6 +589,12 @@ Reference: ${invoiceRef}`;
const amount = this.dataset.amount; const amount = this.dataset.amount;
const decimals = Number(this.dataset.decimals || "18"); const decimals = Number(this.dataset.decimals || "18");
const tokenContract = this.dataset.tokenContract || ""; const tokenContract = this.dataset.tokenContract || "";
let chainAddParams = null;
try {
chainAddParams = this.dataset.chainAdd ? JSON.parse(this.dataset.chainAdd) : null;
} catch (err) {
chainAddParams = null;
}
const setStatus = (msg) => { const setStatus = (msg) => {
if (walletStatus) walletStatus.textContent = msg; if (walletStatus) walletStatus.textContent = msg;
@ -589,7 +613,7 @@ Reference: ${invoiceRef}`;
if (chainId && chainId !== "None" && chainId !== "") { if (chainId && chainId !== "None" && chainId !== "") {
try { try {
await switchChain(Number(chainId)); await switchChain(Number(chainId), chainAddParams);
} catch (err) { } catch (err) {
setStatus(`Chain switch failed: ${err.message || err}`); setStatus(`Chain switch failed: ${err.message || err}`);
this.disabled = false; this.disabled = false;

Loading…
Cancel
Save