Added ether and token sending
This commit is contained in:
parent
c1a1f7af0c
commit
505d5dd2cb
10
css/main.css
10
css/main.css
@ -976,10 +976,14 @@ aside h4 {
|
|||||||
border-radius: 5rem;
|
border-radius: 5rem;
|
||||||
-webkit-animation: popup 1s;
|
-webkit-animation: popup 1s;
|
||||||
animation: popup 1s;
|
animation: popup 1s;
|
||||||
}
|
|
||||||
.user-action-result__icon.success {
|
|
||||||
fill: rgba(var(--background-color), 1);
|
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
.user-action-result__icon.pending {
|
||||||
|
fill: var(--yellow);
|
||||||
|
background-color: rgba(var(--text-color), 0.03);
|
||||||
|
}
|
||||||
|
.user-action-result__icon.confirmed {
|
||||||
|
fill: rgba(var(--background-color), 1);
|
||||||
background-color: #0bbe56;
|
background-color: #0bbe56;
|
||||||
}
|
}
|
||||||
.user-action-result__icon.failed {
|
.user-action-result__icon.failed {
|
||||||
|
|||||||
2
css/main.min.css
vendored
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -914,9 +914,13 @@ aside {
|
|||||||
width: 4rem;
|
width: 4rem;
|
||||||
border-radius: 5rem;
|
border-radius: 5rem;
|
||||||
animation: popup 1s;
|
animation: popup 1s;
|
||||||
&.success {
|
padding: 1rem;
|
||||||
|
&.pending {
|
||||||
|
fill: var(--yellow);
|
||||||
|
background-color: rgba(var(--text-color), 0.03);
|
||||||
|
}
|
||||||
|
&.confirmed {
|
||||||
fill: rgba(var(--background-color), 1);
|
fill: rgba(var(--background-color), 1);
|
||||||
padding: 1rem;
|
|
||||||
background-color: #0bbe56;
|
background-color: #0bbe56;
|
||||||
}
|
}
|
||||||
&.failed {
|
&.failed {
|
||||||
|
|||||||
195
index.html
195
index.html
@ -189,43 +189,33 @@
|
|||||||
let zIndex = 50
|
let zIndex = 50
|
||||||
// function required for popups or modals to appear
|
// function required for popups or modals to appear
|
||||||
function openPopup(popupId, pinned) {
|
function openPopup(popupId, pinned) {
|
||||||
|
if (popupStack.peek() === undefined) {
|
||||||
|
document.addEventListener('keydown', (e) => {
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
closePopup()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
zIndex++
|
zIndex++
|
||||||
getRef(popupId).setAttribute('style', `z-index: ${zIndex}`)
|
getRef(popupId).setAttribute('style', `z-index: ${zIndex}`)
|
||||||
getRef(popupId).show({ pinned })
|
return getRef(popupId).show({ pinned })
|
||||||
return getRef(popupId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// hides the popup or modal
|
// hides the popup or modal
|
||||||
function closePopup() {
|
function closePopup(options = {}) {
|
||||||
if (popupStack.peek() === undefined)
|
if (popupStack.peek() === undefined)
|
||||||
return;
|
return;
|
||||||
popupStack.peek().popup.hide()
|
popupStack.peek().popup.hide(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('popupopened', async e => {
|
document.addEventListener('popupopened', async e => {
|
||||||
switch (e.target.id) {
|
switch (e.target.id) {
|
||||||
case 'saved_ids_popup':
|
|
||||||
const allSavedIds = await getArrayOfSavedIds()
|
|
||||||
const renderedIds = renderContactPickerList(allSavedIds)
|
|
||||||
renderElem(getRef('saved_ids_picker_list'), html`${renderedIds}`)
|
|
||||||
getRef('search_saved_ids_picker').focusIn()
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
document.addEventListener('popupclosed', e => {
|
document.addEventListener('popupclosed', e => {
|
||||||
zIndex--
|
zIndex--
|
||||||
switch (e.target.id) {
|
switch (e.target.id) {
|
||||||
case 'saved_ids_popup':
|
|
||||||
renderElem(getRef('saved_ids_picker_list'), html``)
|
|
||||||
getRef('search_saved_ids_picker').value = ''
|
|
||||||
floGlobals.addressSelectorTarget = null
|
|
||||||
break;
|
|
||||||
case 'transaction_result_popup':
|
|
||||||
renderElem(getRef('transaction_result'), html``)
|
|
||||||
break;
|
|
||||||
case 'retrieve_flo_id_popup':
|
|
||||||
getRef('recovered_flo_id_wrapper').classList.add('hidden')
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
|
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
|
||||||
@ -493,11 +483,6 @@
|
|||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
router.routeTo(location.hash)
|
router.routeTo(location.hash)
|
||||||
document.body.classList.remove('hidden')
|
document.body.classList.remove('hidden')
|
||||||
document.addEventListener('keyup', (e) => {
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
closePopup()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
document.addEventListener('copy', () => {
|
document.addEventListener('copy', () => {
|
||||||
notify('copied', 'success')
|
notify('copied', 'success')
|
||||||
})
|
})
|
||||||
@ -713,7 +698,6 @@
|
|||||||
ethOperator.getTokenBalance({ address: ethAddress, token: 'usdt' })
|
ethOperator.getTokenBalance({ address: ethAddress, token: 'usdt' })
|
||||||
])
|
])
|
||||||
.then(([etherBalance, usdcBalance, usdtBalance]) => {
|
.then(([etherBalance, usdcBalance, usdtBalance]) => {
|
||||||
console.log(etherBalance, usdcBalance, usdtBalance)
|
|
||||||
compactIDB.readData('contacts', floAddress).then(result => {
|
compactIDB.readData('contacts', floAddress).then(result => {
|
||||||
if (result) return
|
if (result) return
|
||||||
compactIDB.addData('contacts', {
|
compactIDB.addData('contacts', {
|
||||||
@ -778,8 +762,11 @@
|
|||||||
<sm-form id="send_tx_form" style="width: min(32rem, 100%)">
|
<sm-form id="send_tx_form" style="width: min(32rem, 100%)">
|
||||||
<fieldset class="flex flex-direction-column gap-0-5">
|
<fieldset class="flex flex-direction-column gap-0-5">
|
||||||
<div class="flex space-between align-center">
|
<div class="flex space-between align-center">
|
||||||
<h4>Sender</h4>
|
<div class="flex flex-direction-column gap-0-5">
|
||||||
<button id="check_balance_button" class="button button--small button--colored" onclick="checkBalance()" disabled>
|
<h4>Sender</h4>
|
||||||
|
<p>Amount will be deducted from equivalent Ethereum address</p>
|
||||||
|
</div>
|
||||||
|
<button id="check_balance_button" class="button button--small button--colored" onclick="checkSenderBalance()" disabled>
|
||||||
Check balance
|
Check balance
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -798,17 +785,17 @@
|
|||||||
<h4>Receiver</h4>
|
<h4>Receiver</h4>
|
||||||
<div class="grid gap-0-5">
|
<div class="grid gap-0-5">
|
||||||
<sm-input class="receiver-address" placeholder="Receiver's Ethereum address" data-eth-address animate required ></sm-input>
|
<sm-input class="receiver-address" placeholder="Receiver's Ethereum address" data-eth-address animate required ></sm-input>
|
||||||
<div class="flex gap-0-5">
|
<div class="flex flex-direction-column gap-0-5">
|
||||||
<sm-input class="receiver-amount amount-shown flex-1" placeholder="Amount" type="number" step="0.000001" min="0.000001" error-text="Amount should be grater than 0.000001 ETHER" animate required>
|
<sm-input class="receiver-amount amount-shown flex-1" placeholder="Amount" type="number" step="0.000001" min="0.000001" error-text="Amount should be grater than 0.000001 ETHER" animate required>
|
||||||
<div class="asset-symbol flex" slot="icon">
|
<div class="asset-symbol flex" slot="icon">
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> <g clip-path="url(#clip0_201_2)"> <path d="M12 0L19.6368 12.4368L12.1633 16.8L4.36325 12.4368L12 0Z"/> <path d="M12 24L4.36325 13.6099L11.8367 18L19.6368 13.6099L12 24Z"/> </g> <defs> <clipPath id="clip0_201_2"> <rect width="24" height="24" fill="white"/> </clipPath> </defs> </svg>
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"> <g clip-path="url(#clip0_201_2)"> <path d="M12 0L19.6368 12.4368L12.1633 16.8L4.36325 12.4368L12 0Z"/> <path d="M12 24L4.36325 13.6099L11.8367 18L19.6368 13.6099L12 24Z"/> </g> <defs> <clipPath id="clip0_201_2"> <rect width="24" height="24" fill="white"/> </clipPath> </defs> </svg>
|
||||||
</div>
|
</div>
|
||||||
</sm-input>
|
</sm-input>
|
||||||
<sm-select id="asset_selector" style="min-width: 6rem" onchange=${handleAssetChange}>
|
<sm-chips id="asset_selector" onchange=${handleAssetChange}>
|
||||||
<sm-option value="ether">ETHER</sm-option>
|
<sm-chip value="ether" selected>ETHER</sm-chip>
|
||||||
<sm-option value="usdc">USDC</sm-option>
|
<sm-chip value="usdc">USDC</sm-chip>
|
||||||
<sm-option value="usdt">USDT</sm-option>
|
<sm-chip value="usdt">USDT</sm-chip>
|
||||||
</sm-select>
|
</sm-chips>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -827,39 +814,34 @@
|
|||||||
target.type = target.type === 'password' ? 'text' : 'password';
|
target.type = target.type === 'password' ? 'text' : 'password';
|
||||||
target.focusIn()
|
target.focusIn()
|
||||||
}
|
}
|
||||||
// function checkBalance() {
|
function checkSenderBalance() {
|
||||||
// let address;
|
let address;
|
||||||
// const hasProvidedPrivateKey = !!getRef('private_key_input')
|
const wif = getRef('private_key_input').value.trim()
|
||||||
// if (hasProvidedPrivateKey) {
|
if (!wif)
|
||||||
// const wif = getRef('private_key_input').value.trim()
|
return notify(`Please enter sender's private key to check balance`)
|
||||||
// if (!wif)
|
address = floEthereum.ethAddressFromPrivateKey(coinjs.wif2privkey(wif).privkey)
|
||||||
// return notify(`Please enter sender's private key to check balance`)
|
getRef('sender_balance_container').classList.remove('hidden')
|
||||||
// address = getTaprootAddress(wif).tr.address
|
renderElem(getRef('sender_balance_container'), html` Loading balance...<sm-spinner></sm-spinner> `)
|
||||||
// } else {
|
const promises = [ethOperator.getBalance(address)]
|
||||||
// address = getRef('taproot_sender_input').value.trim()
|
const selectedAsset = getRef('asset_selector').value
|
||||||
// }
|
if (selectedAsset !== 'ether')
|
||||||
// getRef('sender_balance_container').classList.remove('hidden')
|
promises.push(ethOperator.getTokenBalance({ address, token: selectedAsset }))
|
||||||
// renderElem(getRef('sender_balance_container'), html`
|
Promise.all(promises).then(([ethBalance, tokenBalance]) => {
|
||||||
// Loading balance...<sm-spinner></sm-spinner>
|
renderElem(getRef('sender_balance_container'), html`
|
||||||
// `)
|
<div class="grid gap-1 w-100" style="padding: 1rem; border-radius: 0.5rem; border: solid thin rgba(var(--text-color),0.3)">
|
||||||
// btcOperator.getBalance(address).then(balance => {
|
<div class="grid">
|
||||||
// renderElem(getRef('sender_balance_container'), html`
|
<p class="label">Sender address</p>
|
||||||
// <div class="grid gap-1" style="padding: 1rem; border-radius: 0.5rem; border: solid thin rgba(var(--text-color),0.3)">
|
<sm-copy value=${address}><p>${address}<p></sm-copy>
|
||||||
// ${hasProvidedPrivateKey ? html`
|
</div>
|
||||||
// <div class="grid">
|
<p>
|
||||||
// <p class="label">Sender address</p>
|
Balance: <b class="amount-shown">${ethBalance} ETH</b> ${selectedAsset !== 'ether' ? html`| <b class="amount-shown">${tokenBalance} ${selectedAsset.toUpperCase()}</b>` : ''}
|
||||||
// <sm-copy value=${address}><p>${address}<p></sm-copy>
|
</p>
|
||||||
// </div>
|
</div>
|
||||||
// `: ''}
|
`)
|
||||||
// <p>
|
}).catch(err => {
|
||||||
// Balance: <b class="amount-shown" data-btc-amount=${balance}>${getConvertedAmount(balance, true)}</b>
|
notify(err, 'error')
|
||||||
// </p>
|
})
|
||||||
// </div>
|
}
|
||||||
// `)
|
|
||||||
// }).catch(err => {
|
|
||||||
// notify(e, 'error')
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
function handleSenderInput(e) {
|
function handleSenderInput(e) {
|
||||||
getRef('check_balance_button').disabled = !e.target.isValid
|
getRef('check_balance_button').disabled = !e.target.isValid
|
||||||
if (!e.target.isValid) {
|
if (!e.target.isValid) {
|
||||||
@ -877,61 +859,104 @@
|
|||||||
getRef('send_tx_button').textContent = `Send ${asset.toUpperCase()}`
|
getRef('send_tx_button').textContent = `Send ${asset.toUpperCase()}`
|
||||||
}
|
}
|
||||||
async function sendTx() {
|
async function sendTx() {
|
||||||
|
const receiver = getRef('send_tx_form').querySelector('.receiver-address').value.trim();
|
||||||
|
const amount = getRef('send_tx_form').querySelector('.receiver-amount').value.trim();
|
||||||
|
const asset = getRef('asset_selector').value;
|
||||||
try {
|
try {
|
||||||
const receiver = getRef('send_tx_form').querySelector('.receiver-address').value.trim();
|
|
||||||
const amount = parseFloat(getRef('send_tx_form').querySelector('.receiver-amount').value.trim());
|
|
||||||
const asset = getRef('asset_selector').value;
|
|
||||||
const confirmation = await getConfirmation('Send transaction', {
|
const confirmation = await getConfirmation('Send transaction', {
|
||||||
message: `You are about to send ${amount} ${asset.toUpperCase()} to ${receiver}`,
|
message: `You are about to send ${amount} ${asset.toUpperCase()} to ${receiver}`,
|
||||||
confirmText: 'Send',
|
confirmText: 'Send',
|
||||||
})
|
})
|
||||||
const privateKey = getRef('private_key_input').value.trim()
|
buttonLoader('send_tx_button', true)
|
||||||
|
if (!confirmation) return
|
||||||
|
let privateKey = getRef('private_key_input').value.trim()
|
||||||
|
if (/^[0-9a-fA-F]{64}$/.test(privateKey)) {
|
||||||
|
privateKey = coinjs.privkey2wif(privateKey)
|
||||||
|
}
|
||||||
|
privateKey = coinjs.wif2privkey(privateKey).privkey;
|
||||||
switch (asset) {
|
switch (asset) {
|
||||||
case 'ether': {
|
case 'ether': {
|
||||||
const { tx, hash } = await ethOperator.sendTransaction({
|
const tx = await ethOperator.sendTransaction({
|
||||||
privateKey,
|
privateKey,
|
||||||
receiver,
|
receiver,
|
||||||
amount,
|
amount,
|
||||||
})
|
})
|
||||||
notify(`Transaction sent.`, 'success')
|
showTransactionResult('pending', { txHash: tx.hash })
|
||||||
await tx.wait()
|
await tx.wait()
|
||||||
notify(`Transaction confirmed.`, 'success')
|
showTransactionResult('confirmed', { txHash: tx.hash })
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'usdc':
|
case 'usdc':
|
||||||
case 'usdt': {
|
case 'usdt': {
|
||||||
const { tx, hash } = await ethOperator.sendToken({
|
const tx = await ethOperator.sendToken({
|
||||||
privateKey,
|
privateKey,
|
||||||
receiver,
|
receiver,
|
||||||
amount,
|
amount,
|
||||||
token: asset
|
token: asset
|
||||||
})
|
})
|
||||||
notify(`Transaction sent.`, 'success')
|
showTransactionResult('pending', { txHash: tx.hash })
|
||||||
await tx.wait()
|
await tx.wait()
|
||||||
notify(`Transaction confirmed.`, 'success')
|
showTransactionResult('confirmed', { txHash: tx.hash })
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
getRef('send_tx_form').reset()
|
||||||
|
getRef('sender_balance_container').classList.add('hidden')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e.message)
|
||||||
|
const regex = /\(error=({.*?}),/;
|
||||||
|
const match = e.message.match(regex);
|
||||||
|
if (match && match[1]) {
|
||||||
|
const { code } = JSON.parse(match[1]);
|
||||||
|
if (code === -32000)
|
||||||
|
showTransactionResult('failed', { description: `Insufficient ${asset.toUpperCase()} balance` })
|
||||||
|
else {
|
||||||
|
showTransactionResult('failed', { description: e.message })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
buttonLoader('send_tx_button', false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function showTransactionResult(status, txid) {
|
function showTransactionResult(status, { txHash, description = '' }) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 'success':
|
case 'pending':
|
||||||
renderElem(getRef('transaction_result_popup__content'), html`
|
renderElem(getRef('transaction_result_popup__content'), html`
|
||||||
<svg class="icon user-action-result__icon success" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <path d="M0 0h24v24H0V0z" fill="none" /> <path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z" /> </svg>
|
<svg class="icon user-action-result__icon pending" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/></svg>
|
||||||
<div class="grid gap-0-5 justify-center text-center">
|
<div class="grid gap-0-5 justify-center text-center">
|
||||||
<h4>Transaction sent</h4>
|
<h4>Transaction sent</h4>
|
||||||
<p>Confirmation of transaction might take few hours. </p>
|
<p>Waiting for confirmation from blockchain</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<span class="label">Transaction ID</span>
|
<span class="label">Transaction ID</span>
|
||||||
<sm-copy value=${txid}></sm-copy>
|
<sm-copy value=${txHash}></sm-copy>
|
||||||
</div>
|
</div>
|
||||||
<a class="button button--primary" href=${`https://ranchimall.github.io/btcwallet/#/check_details?query=${txid}`}>Check transaction status</a>
|
<a class="button button--primary" target="_blank" href=${`https://etherscan.io/tx/${txHash}`}>Check transaction status</a>
|
||||||
`)
|
`)
|
||||||
break;
|
break;
|
||||||
|
case 'confirmed':
|
||||||
|
renderElem(getRef('transaction_result_popup__content'), html`
|
||||||
|
<svg class="icon user-action-result__icon confirmed" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <path d="M0 0h24v24H0V0z" fill="none" /> <path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z" /> </svg>
|
||||||
|
<div class="grid gap-0-5 justify-center text-center">
|
||||||
|
<h4>Transaction confirmed</h4>
|
||||||
|
<p>Transaction has been confirmed on the blockchain. </p>
|
||||||
|
</div>
|
||||||
|
<div class="grid">
|
||||||
|
<span class="label">Transaction ID</span>
|
||||||
|
<sm-copy value=${txHash}></sm-copy>
|
||||||
|
</div>
|
||||||
|
<a class="button button--primary" target="_blank" href=${`https://etherscan.io/tx/${txHash}`}>Check transaction status</a>
|
||||||
|
`)
|
||||||
|
break;
|
||||||
|
case 'failed':
|
||||||
|
renderElem(getRef('transaction_result_popup__content'), html`
|
||||||
|
<svg class="icon user-action-result__icon failed" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg>
|
||||||
|
<div class="grid gap-0-5 justify-center text-center">
|
||||||
|
<h4>Transaction failed</h4>
|
||||||
|
<p>${description}</p>
|
||||||
|
</div>
|
||||||
|
`)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
openPopup('transaction_result_popup')
|
openPopup('transaction_result_popup')
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
2
scripts/components.min.js
vendored
2
scripts/components.min.js
vendored
File diff suppressed because one or more lines are too long
@ -273,7 +273,7 @@
|
|||||||
// Get the balance
|
// Get the balance
|
||||||
const provider = getProvider();
|
const provider = getProvider();
|
||||||
const balanceWei = await provider.getBalance(address);
|
const balanceWei = await provider.getBalance(address);
|
||||||
const balanceEth = ethers.utils.formatEther(balanceWei);
|
const balanceEth = parseFloat(ethers.utils.formatEther(balanceWei));
|
||||||
return balanceEth;
|
return balanceEth;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error:', error.message);
|
console.error('Error:', error.message);
|
||||||
@ -291,47 +291,54 @@
|
|||||||
return new Error('Contract address of token not available')
|
return new Error('Contract address of token not available')
|
||||||
const usdcContract = new ethers.Contract(CONTRACT_ADDRESSES['usdc'] || contractAddress, ERC20ABI, getProvider());
|
const usdcContract = new ethers.Contract(CONTRACT_ADDRESSES['usdc'] || contractAddress, ERC20ABI, getProvider());
|
||||||
let balance = await usdcContract.balanceOf(address);
|
let balance = await usdcContract.balanceOf(address);
|
||||||
balance = ethers.utils.formatUnits(balance, 6); // Assuming 6 decimals
|
balance = parseFloat(ethers.utils.formatUnits(balance, 6)); // Assuming 6 decimals
|
||||||
return balance;
|
return balance;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendTransaction = ethOperator.sendTransaction = async ({ privateKey, receiver, amount }) => {
|
const estimateGas = ethOperator.estimateGas = async ({ privateKey, receiver, amount }) => {
|
||||||
const provider = getProvider();
|
try {
|
||||||
const signer = new ethers.Wallet(privateKey, provider);
|
const provider = getProvider();
|
||||||
const limit = provider.estimateGas({
|
const signer = new ethers.Wallet(privateKey, provider);
|
||||||
from: signer.address,
|
return provider.estimateGas({
|
||||||
to: receiver,
|
from: signer.address,
|
||||||
value: ethers.utils.parseUnits(amount, "ether"),
|
to: receiver,
|
||||||
});
|
value: ethers.utils.parseUnits(amount, "ether"),
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Creating and sending the transaction object
|
const sendTransaction = ethOperator.sendTransaction = async ({ privateKey, receiver, amount }) => {
|
||||||
const tx = await signer.sendTransaction({
|
try {
|
||||||
to: receiver,
|
const provider = getProvider();
|
||||||
value: ethers.utils.parseUnits(amount, "ether"),
|
const signer = new ethers.Wallet(privateKey, provider);
|
||||||
gasLimit: limit,
|
const limit = await estimateGas({ privateKey, receiver, amount })
|
||||||
nonce: signer.getTransactionCount(),
|
// Creating and sending the transaction object
|
||||||
maxPriorityFeePerGas: ethers.utils.parseUnits("2", "gwei"),
|
return signer.sendTransaction({
|
||||||
});
|
to: receiver,
|
||||||
return { tx, hash: tx.hash }
|
value: ethers.utils.parseUnits(amount, "ether"),
|
||||||
|
gasLimit: limit,
|
||||||
|
nonce: signer.getTransactionCount(),
|
||||||
|
maxPriorityFeePerGas: ethers.utils.parseUnits("2", "gwei"),
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendToken = ethOperator.sendToken = async ({ token, privateKey, amount, receiver, contractAddress }) => {
|
const sendToken = ethOperator.sendToken = async ({ token, privateKey, amount, receiver, contractAddress }) => {
|
||||||
try {
|
// Create a wallet using the private key
|
||||||
// Create a wallet using the private key
|
const wallet = new ethers.Wallet(privateKey, getProvider());
|
||||||
const wallet = new ethers.Wallet(privateKey, getProvider());
|
// Contract interface
|
||||||
// Contract interface
|
const tokenContract = new ethers.Contract(CONTRACT_ADDRESSES[token] || contractAddress, ERC20ABI, wallet);
|
||||||
const tokenContract = new ethers.Contract(CONTRACT_ADDRESSES[token] || contractAddress, ERC20ABI, wallet);
|
// Convert the amount to the smallest unit of USDC (wei)
|
||||||
// Convert the amount to the smallest unit of USDC (wei)
|
const amountWei = ethers.utils.parseUnits(amount.toString(), 6); // Assuming 6 decimals for USDC
|
||||||
const amountWei = ethers.utils.parseUnits(amount.toString(), 6); // Assuming 6 decimals for USDC
|
|
||||||
|
|
||||||
// Call the transfer function on the USDC contract
|
// Call the transfer function on the USDC contract
|
||||||
const tx = await tokenContract.transfer(receiver, amountWei);
|
return tokenContract.transfer(receiver, amountWei)
|
||||||
return { tx, hash: tx.hash }
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error:', error.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})('object' === typeof module ? module.exports : window.ethOperator = {});
|
})('object' === typeof module ? module.exports : window.ethOperator = {});
|
||||||
|
|||||||
2
scripts/ethOperator.min.js
vendored
2
scripts/ethOperator.min.js
vendored
@ -1 +1 @@
|
|||||||
!function(EXPORTS){if(!window.ethers)return console.error("ethers.js not found");const ethOperator=EXPORTS,isValidAddress=ethOperator.isValidAddress=address=>{try{const isValidChecksum=ethers.utils.isAddress(address),isValidNonChecksum=ethers.utils.getAddress(address)===address.toLowerCase();return isValidChecksum||isValidNonChecksum}catch(error){return!1}},ERC20ABI=[{constant:!0,inputs:[],name:"name",outputs:[{name:"",type:"string"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_spender",type:"address"},{name:"_value",type:"uint256"}],name:"approve",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[],name:"totalSupply",outputs:[{name:"",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_from",type:"address"},{name:"_to",type:"address"},{name:"_value",type:"uint256"}],name:"transferFrom",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[],name:"decimals",outputs:[{name:"",type:"uint8"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[{name:"_owner",type:"address"}],name:"balanceOf",outputs:[{name:"balance",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[],name:"symbol",outputs:[{name:"",type:"string"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_to",type:"address"},{name:"_value",type:"uint256"}],name:"transfer",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[{name:"_owner",type:"address"},{name:"_spender",type:"address"}],name:"allowance",outputs:[{name:"",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{payable:!0,stateMutability:"payable",type:"fallback"},{anonymous:!1,inputs:[{indexed:!0,name:"owner",type:"address"},{indexed:!0,name:"spender",type:"address"},{indexed:!1,name:"value",type:"uint256"}],name:"Approval",type:"event"},{anonymous:!1,inputs:[{indexed:!0,name:"from",type:"address"},{indexed:!0,name:"to",type:"address"},{indexed:!1,name:"value",type:"uint256"}],name:"Transfer",type:"event"}],CONTRACT_ADDRESSES={usdc:"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",usdt:"0xdac17f958d2ee523a2206206994597c13d831ec7"};function getProvider(){return window.ethereum?new ethers.providers.Web3Provider(window.ethereum):new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/6e12fee52bdd48208f0d82fb345bcb3c")}ethOperator.getBalance=async address=>{try{if(!address||!isValidAddress(address))return new Error("Invalid address");const provider=getProvider(),balanceWei=await provider.getBalance(address);return ethers.utils.formatEther(balanceWei)}catch(error){return console.error("Error:",error.message),error}},ethOperator.getTokenBalance=async({address:address,token:token,contractAddress:contractAddress})=>{try{if(!token)return new Error("Token not specified");if(!CONTRACT_ADDRESSES[token]&&contractAddress)return new Error("Contract address of token not available");const usdcContract=new ethers.Contract(CONTRACT_ADDRESSES.usdc||contractAddress,ERC20ABI,getProvider());let balance=await usdcContract.balanceOf(address);return balance=ethers.utils.formatUnits(balance,6),balance}catch(e){console.error(e)}},ethOperator.sendTransaction=async({privateKey:privateKey,receiver:receiver,amount:amount})=>{const provider=getProvider(),signer=new ethers.Wallet(privateKey,provider),limit=provider.estimateGas({from:signer.address,to:receiver,value:ethers.utils.parseUnits(amount,"ether")}),tx=await signer.sendTransaction({to:receiver,value:ethers.utils.parseUnits(amount,"ether"),gasLimit:limit,nonce:signer.getTransactionCount(),maxPriorityFeePerGas:ethers.utils.parseUnits("2","gwei")});return{tx:tx,hash:tx.hash}},ethOperator.sendToken=async({token:token,privateKey:privateKey,amount:amount,receiver:receiver,contractAddress:contractAddress})=>{try{const wallet=new ethers.Wallet(privateKey,getProvider()),tokenContract=new ethers.Contract(CONTRACT_ADDRESSES[token]||contractAddress,ERC20ABI,wallet),amountWei=ethers.utils.parseUnits(amount.toString(),6),tx=await tokenContract.transfer(receiver,amountWei);return{tx:tx,hash:tx.hash}}catch(error){console.error("Error:",error.message)}}}("object"==typeof module?module.exports:window.ethOperator={});
|
!function(EXPORTS){if(!window.ethers)return console.error("ethers.js not found");const ethOperator=EXPORTS,isValidAddress=ethOperator.isValidAddress=address=>{try{const isValidChecksum=ethers.utils.isAddress(address),isValidNonChecksum=ethers.utils.getAddress(address)===address.toLowerCase();return isValidChecksum||isValidNonChecksum}catch(error){return!1}},ERC20ABI=[{constant:!0,inputs:[],name:"name",outputs:[{name:"",type:"string"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_spender",type:"address"},{name:"_value",type:"uint256"}],name:"approve",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[],name:"totalSupply",outputs:[{name:"",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_from",type:"address"},{name:"_to",type:"address"},{name:"_value",type:"uint256"}],name:"transferFrom",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[],name:"decimals",outputs:[{name:"",type:"uint8"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[{name:"_owner",type:"address"}],name:"balanceOf",outputs:[{name:"balance",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{constant:!0,inputs:[],name:"symbol",outputs:[{name:"",type:"string"}],payable:!1,stateMutability:"view",type:"function"},{constant:!1,inputs:[{name:"_to",type:"address"},{name:"_value",type:"uint256"}],name:"transfer",outputs:[{name:"",type:"bool"}],payable:!1,stateMutability:"nonpayable",type:"function"},{constant:!0,inputs:[{name:"_owner",type:"address"},{name:"_spender",type:"address"}],name:"allowance",outputs:[{name:"",type:"uint256"}],payable:!1,stateMutability:"view",type:"function"},{payable:!0,stateMutability:"payable",type:"fallback"},{anonymous:!1,inputs:[{indexed:!0,name:"owner",type:"address"},{indexed:!0,name:"spender",type:"address"},{indexed:!1,name:"value",type:"uint256"}],name:"Approval",type:"event"},{anonymous:!1,inputs:[{indexed:!0,name:"from",type:"address"},{indexed:!0,name:"to",type:"address"},{indexed:!1,name:"value",type:"uint256"}],name:"Transfer",type:"event"}],CONTRACT_ADDRESSES={usdc:"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",usdt:"0xdac17f958d2ee523a2206206994597c13d831ec7"};function getProvider(){return window.ethereum?new ethers.providers.Web3Provider(window.ethereum):new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/6e12fee52bdd48208f0d82fb345bcb3c")}ethOperator.getBalance=async address=>{try{if(!address||!isValidAddress(address))return new Error("Invalid address");const provider=getProvider(),balanceWei=await provider.getBalance(address);return parseFloat(ethers.utils.formatEther(balanceWei))}catch(error){return console.error("Error:",error.message),error}},ethOperator.getTokenBalance=async({address:address,token:token,contractAddress:contractAddress})=>{try{if(!token)return new Error("Token not specified");if(!CONTRACT_ADDRESSES[token]&&contractAddress)return new Error("Contract address of token not available");const usdcContract=new ethers.Contract(CONTRACT_ADDRESSES.usdc||contractAddress,ERC20ABI,getProvider());let balance=await usdcContract.balanceOf(address);return balance=parseFloat(ethers.utils.formatUnits(balance,6)),balance}catch(e){console.error(e)}};const estimateGas=ethOperator.estimateGas=async({privateKey:privateKey,receiver:receiver,amount:amount})=>{try{const provider=getProvider(),signer=new ethers.Wallet(privateKey,provider);return provider.estimateGas({from:signer.address,to:receiver,value:ethers.utils.parseUnits(amount,"ether")})}catch(e){throw new Error(e)}};ethOperator.sendTransaction=async({privateKey:privateKey,receiver:receiver,amount:amount})=>{try{const provider=getProvider(),signer=new ethers.Wallet(privateKey,provider),limit=await estimateGas({privateKey:privateKey,receiver:receiver,amount:amount});return signer.sendTransaction({to:receiver,value:ethers.utils.parseUnits(amount,"ether"),gasLimit:limit,nonce:signer.getTransactionCount(),maxPriorityFeePerGas:ethers.utils.parseUnits("2","gwei")})}catch(e){throw new Error(e)}},ethOperator.sendToken=async({token:token,privateKey:privateKey,amount:amount,receiver:receiver,contractAddress:contractAddress})=>{const wallet=new ethers.Wallet(privateKey,getProvider()),tokenContract=new ethers.Contract(CONTRACT_ADDRESSES[token]||contractAddress,ERC20ABI,wallet),amountWei=ethers.utils.parseUnits(amount.toString(),6);return tokenContract.transfer(receiver,amountWei)}}("object"==typeof module?module.exports:window.ethOperator={});
|
||||||
Loading…
Reference in New Issue
Block a user