Skip to content

Instantly share code, notes, and snippets.

@34r7h
Created November 6, 2025 05:25
Show Gist options
  • Save 34r7h/8fa2db51a438e7c5e9d7910bcd8bc733 to your computer and use it in GitHub Desktop.
Save 34r7h/8fa2db51a438e7c5e9d7910bcd8bc733 to your computer and use it in GitHub Desktop.
// Multi-Chain Token Payment Integration Script (OG + Polygon)
(function () {
"use strict";
console.log("πŸš€ Multi-Chain Payment Script: Starting...");
// Load Web3 from CDN if not available
if (typeof window.Web3 === "undefined") {
console.log("πŸ“¦ Loading Web3...");
const script = document.createElement("script");
script.src = "https://cdn.jsdelivr.net/npm/[email protected]/dist/web3.min.js";
script.onload = initMultiChainPayment;
document.head.appendChild(script);
} else {
initMultiChainPayment();
}
// Network Configurations
const NETWORKS = {
OG: {
chainId: "0x40D9", // 16601 in hex
chainName: "0G-Galileo-Testnet",
rpcUrls: ["https://evmrpc-testnet.0g.ai"],
blockExplorerUrls: ["https://chainscan-galileo.0g.ai"],
nativeCurrency: {
name: "OG",
symbol: "OG",
decimals: 18,
},
receivingAddress: "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d1b5", // Replace with your address
conversionRate: 10, // 1 OG = $10 USD
},
POLYGON: {
chainId: "0x89", // 137 in hex (Polygon Mainnet)
chainName: "Polygon Mainnet",
rpcUrls: ["https://polygon-rpc.com"],
blockExplorerUrls: ["https://polygonscan.com"],
nativeCurrency: {
name: "MATIC",
symbol: "MATIC",
decimals: 18,
},
receivingAddress: "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d1b5", // Replace with your address
conversionRate: 0.5, // 1 MATIC = $0.50 USD (adjust as needed)
},
};
function initMultiChainPayment() {
console.log("πŸ”§ Multi-Chain Payment Script: Initializing...");
const store = window.$store;
const state = window.$state;
const api = window.$api;
if (!store || !state) {
console.error("❌ Store not available");
return;
}
console.log("βœ… Store available:", store);
console.log("βœ… State available:", state);
// Add payment options
addCryptoPaymentOptions();
// Override transact action
const originalTransact = store._actions.transact[0];
store._actions.transact[0] = async function (context, payload) {
console.log("πŸ’³ Transact called:", payload);
if (payload.payment) {
const paymentType = payload.payment["payment-type"];
if (paymentType === "OG Token") {
console.log("πŸͺ™ Processing OG Token payment...");
return await handleCompletePayment(payload, "OG");
} else if (paymentType === "Polygon") {
console.log("🟣 Processing Polygon payment...");
return await handleCompletePayment(payload, "POLYGON");
} else if (paymentType === "Polygon Testnet") {
console.log("🟣 Processing Polygon Testnet payment...");
return await handleCompletePayment(payload, "POLYGON_TESTNET");
}
}
return originalTransact.call(this, context, payload);
};
// Prevent form submission until payment is confirmed
const originalSubmitMethod = store._actions.submitMethod;
if (originalSubmitMethod) {
store._actions.submitMethod = async function (context, payload) {
console.log("πŸ“ Submit method called:", payload);
if (
payload.type === "order" &&
payload.data &&
payload.data.payment
) {
const paymentType = payload.data.payment["payment-type"];
if (
["OG Token", "Polygon", "Polygon Testnet"].includes(paymentType)
) {
if (!window.cryptoPaymentCompleted) {
console.log(
"🚫 Blocking order submission - payment must be completed first"
);
alert(
"Please complete the crypto payment before submitting the order."
);
return { success: false, error: "Payment not completed" };
} else {
console.log("βœ… Payment completed, allowing order submission");
}
}
}
return originalSubmitMethod.call(this, context, payload);
};
}
// Add icons
if (state.icons) {
state.icons.OG = "fas fa-coins";
state.icons.MATIC = "fas fa-gem";
state.icons.Polygon = "fas fa-gem";
}
console.log("πŸŽ‰ Multi-Chain Payment Script: Initialization complete!");
}
function addCryptoPaymentOptions() {
const state = window.$state;
if (!state.models) state.models = {};
if (!state.models.iform) state.models.iform = {};
if (!state.models.iform.checkout) {
// Create checkout form
state.models.iform.checkout = {
name: "Checkout",
forms: [
{
name: "Shipping",
inputs: [
{
inputType: "input",
label: "name",
type: "text",
placeholder: "Your Name",
required: true,
},
{
inputType: "input",
label: "street",
type: "text",
placeholder: "Street address",
required: true,
},
{
inputType: "input",
label: "city",
type: "text",
placeholder: "City / town",
required: true,
},
{
inputType: "input",
label: "country",
type: "text",
placeholder: "Country",
required: true,
},
{
inputType: "input",
label: "zip",
type: "text",
placeholder: "Zip / postal code",
required: true,
},
],
},
{
name: "Payment",
inputs: [
{
inputType: "select",
label: "payment-type",
type: "text",
placeholder: "Select payment method",
options: [
{ name: "Credit", icon: "fas fa-credit-card" },
{ name: "PayPal", icon: "fab fa-paypal" },
{ name: "Crypto", icon: "fab fa-btc" },
{
name: "OG Token",
icon: "fas fa-coins",
content: createPaymentOptionContent(
"OG Token",
"0G Network",
"#ff6b35",
"#f7931e",
"fas fa-coins"
),
},
{
name: "Polygon",
icon: "fas fa-gem",
content: createPaymentOptionContent(
"Polygon",
"Polygon Mainnet",
"#8247e5",
"#6b3bd7",
"fas fa-gem"
),
},
{
name: "Polygon Testnet",
icon: "fas fa-gem",
content: createPaymentOptionContent(
"Polygon Testnet",
"Polygon Amoy Testnet",
"#8247e5",
"#6b3bd7",
"fas fa-gem"
),
},
],
required: true,
},
// Credit card fields
{
inputType: "input",
label: "number",
type: "text",
placeholder: "Card Number",
if: ["payment-type", "Credit"],
},
{
inputType: "input",
label: "month",
type: "text",
placeholder: "MM",
if: ["payment-type", "Credit"],
},
{
inputType: "input",
label: "year",
type: "text",
placeholder: "YY",
if: ["payment-type", "Credit"],
},
{
inputType: "input",
label: "cvc",
type: "text",
placeholder: "CVC",
if: ["payment-type", "Credit"],
},
// Crypto fields
{
inputType: "select",
label: "currency",
type: "text",
options: ["bitcoin", "ethereum", "litecoin"],
if: ["payment-type", "Crypto"],
},
// OG Token wallet section
{
inputType: "div",
label: "og-wallet",
if: ["payment-type", "OG Token"],
content: createWalletConnectionContent("OG Token"),
},
// Polygon wallet section
{
inputType: "div",
label: "polygon-wallet",
if: ["payment-type", "Polygon"],
content: createWalletConnectionContent("Polygon"),
},
// Polygon Testnet wallet section
{
inputType: "div",
label: "polygon-testnet-wallet",
if: ["payment-type", "Polygon Testnet"],
content: createWalletConnectionContent("Polygon Testnet"),
},
],
},
],
submit: {
method: "create",
type: "order",
},
};
} else {
// Modify existing checkout form
const paymentForm = state.models.iform.checkout.forms.find(
(f) => f.name === "Payment"
);
if (paymentForm) {
const paymentTypeInput = paymentForm.inputs.find(
(i) => i.label === "payment-type"
);
if (paymentTypeInput && paymentTypeInput.options) {
// Add OG Token if not exists
if (
!paymentTypeInput.options.some((opt) => opt.name === "OG Token")
) {
paymentTypeInput.options.push({
name: "OG Token",
icon: "fas fa-coins",
content: createPaymentOptionContent(
"OG Token",
"0G Network",
"#ff6b35",
"#f7931e",
"fas fa-coins"
),
});
}
// Add Polygon if not exists
if (!paymentTypeInput.options.some((opt) => opt.name === "Polygon")) {
paymentTypeInput.options.push({
name: "Polygon",
icon: "fas fa-gem",
content: createPaymentOptionContent(
"Polygon",
"Polygon Mainnet",
"#8247e5",
"#6b3bd7",
"fas fa-gem"
),
});
}
// Add Polygon Testnet if not exists
if (
!paymentTypeInput.options.some(
(opt) => opt.name === "Polygon Testnet"
)
) {
paymentTypeInput.options.push({
name: "Polygon Testnet",
icon: "fas fa-gem",
content: createPaymentOptionContent(
"Polygon Testnet",
"Polygon Amoy Testnet",
"#8247e5",
"#6b3bd7",
"fas fa-gem"
),
});
}
}
// Add wallet connection fields
const walletFields = [
{
label: "og-wallet",
if: ["payment-type", "OG Token"],
network: "OG Token",
},
{
label: "polygon-wallet",
if: ["payment-type", "Polygon"],
network: "Polygon",
},
{
label: "polygon-testnet-wallet",
if: ["payment-type", "Polygon Testnet"],
network: "Polygon Testnet",
},
];
walletFields.forEach((field) => {
if (!paymentForm.inputs.some((i) => i.label === field.label)) {
paymentForm.inputs.push({
inputType: "div",
label: field.label,
if: field.if,
content: createWalletConnectionContent(field.network),
});
}
});
}
}
console.log("πŸ“‹ Final checkout form:", state.models.iform.checkout);
// Setup event listeners
setTimeout(setupEventListeners, 1000);
}
function createPaymentOptionContent(name, network, color1, color2, icon) {
const buttonId = `connect-wallet-btn-option-${name.toLowerCase().replace(/\s+/g, "-")}`;
return `
<div style="text-align: left; padding: 12px; background: linear-gradient(135deg, ${color1}, ${color2}); border-radius: 8px; color: white; margin: 4px 0;">
<div style="display: flex; align-items: center; margin-bottom: 8px;">
<i class="${icon}" style="font-size: 24px; margin-right: 8px;"></i>
<strong style="font-size: 16px;">Pay with ${network}</strong>
<button id="${buttonId}" style="
background: rgba(255,255,255,0.2);
color: white;
border: 1px solid rgba(255,255,255,0.3);
padding: 6px 12px;
border-radius: 4px;
font-size: 12px;
font-weight: bold;
cursor: pointer;
margin-left: auto;
transition: all 0.3s ease;
" onclick="event.stopPropagation(); window.handleConnectWallet('${name}');">
<i class="fas fa-wallet"></i> Connect Wallet
</button>
</div>
<div style="font-size: 12px; opacity: 0.9; line-height: 1.4;">
<div style="margin-bottom: 3px;">βœ“ Connect your MetaMask wallet</div>
<div style="margin-bottom: 3px;">βœ“ Payment processed instantly</div>
<div style="margin-bottom: 3px;">βœ“ Order completed automatically</div>
<div>βœ“ Secure blockchain transaction</div>
</div>
</div>
`;
}
function createWalletConnectionContent(network) {
const buttonId = `connect-wallet-btn-${network.toLowerCase().replace(/\s+/g, "-")}`;
return `
<div style="text-align: left; padding: 16px; background: #f8f9fa; border-radius: 8px; margin-top: 12px; border-left: 4px solid #007bff;">
<div style="font-size: 16px; font-weight: bold; color: #333; margin-bottom: 12px; display: flex; align-items: center;">
<i class="fas fa-wallet" style="color: #007bff; margin-right: 8px; font-size: 18px;"></i>
Connect Your Wallet
</div>
<div style="font-size: 14px; color: #666; line-height: 1.6; margin-bottom: 16px;">
To pay with ${network}, you need to connect your MetaMask wallet first.
</div>
<div id="wallet-address-display-${buttonId}" style="display: none; font-size: 12px; color: #28a745; font-weight: bold; margin-bottom: 16px; padding: 8px; background: #d4edda; border-radius: 4px;">
<i class="fas fa-check-circle"></i> Connected: <span class="wallet-address"></span>
</div>
<button id="${buttonId}" style="
background: linear-gradient(135deg, #007bff, #0056b3);
color: white;
border: none;
padding: 12px 24px;
border-radius: 6px;
font-size: 14px;
font-weight: bold;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s ease;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
" onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 4px 8px rgba(0,0,0,0.2)'" onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 2px 4px rgba(0,0,0,0.1)'">
<i class="fas fa-wallet"></i>
Connect MetaMask Wallet
</button>
<div style="font-size: 12px; color: #999; margin-top: 12px; padding: 8px; background: #e9ecef; border-radius: 4px; font-style: italic;">
<i class="fas fa-info-circle" style="margin-right: 4px;"></i>
<strong>Note:</strong> You need MetaMask installed.
<a href="https://metamask.io" target="_blank" style="color: #007bff; text-decoration: underline;">Download MetaMask</a>
</div>
</div>
`;
}
function setupEventListeners() {
const networks = ["OG Token", "Polygon", "Polygon Testnet"];
networks.forEach((network) => {
const safeName = network.toLowerCase().replace(/\s+/g, "-");
const connectBtn = document.getElementById(`connect-wallet-btn-${safeName}`);
const connectBtnOption = document.getElementById(`connect-wallet-btn-option-${safeName}`);
if (connectBtn) {
connectBtn.addEventListener("click", () => window.handleConnectWallet(network));
console.log(`βœ… Connect wallet button added for ${network}`);
}
if (connectBtnOption) {
connectBtnOption.addEventListener("click", (e) => {
e.stopPropagation();
window.handleConnectWallet(network);
});
console.log(`βœ… Connect wallet option button added for ${network}`);
}
});
}
// Global connect wallet handler
window.handleConnectWallet = async function (networkName) {
try {
console.log(`πŸ”„ Connecting to MetaMask for ${networkName}...`);
if (typeof window.ethereum === "undefined") {
throw new Error(
"MetaMask not found. Please install MetaMask to use crypto payments."
);
}
// Request account access
const accounts = await window.ethereum.request({
method: "eth_requestAccounts",
});
const userAddress = accounts[0];
console.log("πŸ‘€ Connected to MetaMask:", userAddress);
// Switch to appropriate network
const networkKey = networkName === "OG Token" ? "OG" :
networkName === "Polygon" ? "POLYGON" : "POLYGON_TESTNET";
console.log(`πŸ”„ Switching to ${networkName}...`);
await switchToNetwork(networkKey);
// Update UI
const safeName = networkName.toLowerCase().replace(/\s+/g, "-");
const connectBtn = document.getElementById(`connect-wallet-btn-${safeName}`);
const connectBtnOption = document.getElementById(`connect-wallet-btn-option-${safeName}`);
const addressDisplay = document.getElementById(`wallet-address-display-connect-wallet-btn-${safeName}`);
if (connectBtn) {
connectBtn.innerHTML = '<i class="fas fa-check"></i> Wallet Connected';
connectBtn.style.background = "linear-gradient(135deg, #28a745, #20c997)";
connectBtn.disabled = true;
}
if (connectBtnOption) {
connectBtnOption.innerHTML = '<i class="fas fa-check"></i> Connected';
connectBtnOption.style.background = "rgba(40, 167, 69, 0.3)";
connectBtnOption.style.borderColor = "rgba(40, 167, 69, 0.5)";
connectBtnOption.disabled = true;
}
if (addressDisplay) {
const addressSpan = addressDisplay.querySelector(".wallet-address");
if (addressSpan) {
addressSpan.textContent = `${userAddress.substring(0, 6)}...${userAddress.substring(userAddress.length - 4)}`;
}
addressDisplay.style.display = "block";
}
console.log(`βœ… Wallet connected successfully to ${networkName}!`);
} catch (error) {
console.error("❌ Wallet connection error:", error);
alert(`Wallet Connection Failed: ${error.message}\n\nPlease make sure MetaMask is installed and try again.`);
}
};
// Complete payment handler
async function handleCompletePayment(payload, networkKey) {
try {
if (typeof window.ethereum === "undefined") {
throw new Error(
"MetaMask not found. Please install MetaMask to use crypto payments."
);
}
console.log(`πŸ”„ Starting ${networkKey} payment flow...`);
const network = NETWORKS[networkKey];
// Connect to MetaMask
const accounts = await window.ethereum.request({
method: "eth_requestAccounts",
});
const userAddress = accounts[0];
console.log("πŸ‘€ Connected to MetaMask:", userAddress);
// Switch to network
await switchToNetwork(networkKey);
// Calculate payment amount
const usdAmount = parseFloat(payload.fullOrder.total);
const tokenAmount = usdAmount / network.conversionRate;
const tokenAmountWei = window.Web3.utils.toWei(
tokenAmount.toString(),
"ether"
);
console.log(
`πŸ’° Payment: $${usdAmount} USD = ${tokenAmount} ${network.nativeCurrency.symbol}`
);
// Create transaction
const transaction = {
from: userAddress,
to: network.receivingAddress,
value: tokenAmountWei,
gas: "0x5208",
gasPrice: "0x3B9ACA00",
};
console.log("πŸš€ Sending transaction...");
const txHash = await window.ethereum.request({
method: "eth_sendTransaction",
params: [transaction],
});
console.log("βœ… Transaction sent:", txHash);
// Wait for confirmation
console.log("⏳ Waiting for confirmation...");
const receipt = await waitForTransactionConfirmation(txHash);
if (receipt && receipt.status === "0x1") {
console.log("βœ… Transaction confirmed!");
// Update order
await window.$api("update", {
type: "orders",
id: payload.orderId,
data: {
paid: network.chainName,
txHash: txHash,
tokenAmount: tokenAmount.toString(),
tokenSymbol: network.nativeCurrency.symbol,
network: network.chainName,
status: "paid",
paymentConfirmed: true,
},
});
// Set completion flag
window.cryptoPaymentCompleted = true;
// Complete order
const originalTransact = window.$store._actions.transact[0];
await originalTransact.call(window.$store, payload);
// Send notification
await window.$api("notify", {
type: "billing",
message: `${network.nativeCurrency.symbol} payment successful! TX: ${txHash.substring(0, 10)}...`,
to: [window.$state.auth.uid],
from: "Crypto Payment",
link: `/orders/${payload.orderId}`,
id: payload.orderId,
});
alert(`Payment Successful! πŸŽ‰\n\nTransaction Hash: ${txHash}\nAmount: ${tokenAmount} ${network.nativeCurrency.symbol} ($${usdAmount} USD)\nNetwork: ${network.chainName}\n\nYour order has been processed!`);
return {
success: true,
txHash: txHash,
tokenAmount: tokenAmount,
orderId: payload.orderId,
};
} else {
throw new Error("Transaction failed or was rejected");
}
} catch (error) {
console.error("❌ Payment error:", error);
alert(`Payment Failed: ${error.message}\n\nPlease try again or contact support.`);
throw error;
}
}
// Global payment completion flag
window.cryptoPaymentCompleted = false;
// Network switching function
async function switchToNetwork(networkKey) {
const network = NETWORKS[networkKey];
try {
await window.ethereum.request({
method: "wallet_switchEthereumChain",
params: [{ chainId: network.chainId }],
});
console.log(`βœ… Switched to ${network.chainName}`);
} catch (switchError) {
if (switchError.code === 4902) {
console.log(`βž• Adding ${network.chainName} to MetaMask...`);
try {
await window.ethereum.request({
method: "wallet_addEthereumChain",
params: [network],
});
console.log(`βœ… Added ${network.chainName} to MetaMask`);
} catch (addError) {
throw new Error(
`Failed to add ${network.chainName}: ${addError.message}`
);
}
} else {
throw new Error(
`Failed to switch to ${network.chainName}: ${switchError.message}`
);
}
}
}
// Transaction confirmation waiting
function waitForTransactionConfirmation(txHash) {
return new Promise((resolve, reject) => {
const checkConfirmation = async () => {
try {
const receipt = await window.ethereum.request({
method: "eth_getTransactionReceipt",
params: [txHash],
});
if (receipt) {
resolve(receipt);
} else {
setTimeout(checkConfirmation, 2000);
}
} catch (error) {
reject(error);
}
};
checkConfirmation();
});
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment