Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c26a778e54 | ||
|
|
b8f0dd296e | ||
|
|
cf8dc49082 | ||
|
|
371771080e | ||
|
|
b80d588793 | ||
|
|
d8b18a42f8 | ||
|
|
131ecf5bb4 | ||
|
|
e587e3ac98 | ||
|
|
b3ce434325 | ||
|
|
008231738e | ||
|
|
deb352cf03 | ||
|
|
36dbf379b1 | ||
|
|
30d4a0e6bb | ||
|
|
1ebbf51bb4 | ||
|
|
af0ecf4a13 | ||
|
|
01c206388e | ||
|
|
8b6f8cac7d | ||
|
|
1b79c0c351 | ||
|
|
faf411aa4b | ||
|
|
b8e1fab1c4 | ||
|
|
42ba20a5bf | ||
|
|
f943ea4609 | ||
|
|
851fc56199 | ||
|
|
047d8c5e0a | ||
|
|
8b19f3ac36 |
212
index.html
212
index.html
@ -16,9 +16,9 @@
|
||||
<script>
|
||||
/* Constants for FLO blockchain operations !!Make sure to add this at beginning!! */
|
||||
const floGlobals = {
|
||||
blockchain: "FLO",
|
||||
tokenApiUrl: 'https://ranchimallflo.duckdns.org',
|
||||
tokenURL: 'https://ranchimallflo.duckdns.org/',
|
||||
blockchain: "FLO_TEST",
|
||||
tokenApiUrl: 'https://ranchimallflo-testnet-blockbook.ranchimall.net',
|
||||
tokenURL: 'https://ranchimallflo-testnet-blockbook.ranchimall.net/',
|
||||
expirationDays: 60,
|
||||
}
|
||||
</script>
|
||||
@ -43,7 +43,7 @@
|
||||
compactIDB.initDB("FLOwebWallet", IDBObjects).then(async result => {
|
||||
render.savedIds();
|
||||
if (!floGlobals.tokens || !floGlobals.smartContracts) {
|
||||
fetchJSON(`${floGlobals.tokenApiUrl}/api/v2/tokenSmartContractList`).then(({ tokens, smartContracts }) => {
|
||||
fetchJson(`${floGlobals.tokenApiUrl}/api/v2/tokenSmartContractList`).then(({ tokens, smartContracts }) => {
|
||||
floGlobals.scMap = new Map()
|
||||
floGlobals.tokens = tokens.sort((a, b) => a.localeCompare(b))
|
||||
floGlobals.smartContracts = smartContracts
|
||||
@ -54,11 +54,7 @@
|
||||
routeTo(window.location.hash, { firstLoad: true })
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
if (window.location.hash.includes('smartcontracts'))
|
||||
routeTo('', { firstLoad: true })
|
||||
else
|
||||
routeTo(window.location.hash, { firstLoad: true })
|
||||
getRef('smart_contract_link').classList.add('hidden')
|
||||
routeTo(window.location.hash, { firstLoad: true, smartContractsUnavailable: true })
|
||||
}).finally(() => {
|
||||
loader(false)
|
||||
})
|
||||
@ -208,7 +204,7 @@
|
||||
class="button justify-self-center hidden">Load more</button>
|
||||
</section>
|
||||
</div>
|
||||
<div id="pagination_wrapper" class="flex gap-0-3 align-center"> </div>
|
||||
<div id="pagination_wrapper" class="flex gap-0-3 align-center"></div>
|
||||
</div>
|
||||
<div id="contacts" class="page flex h-100">
|
||||
<div class="flex direction-column gap-2 h-100">
|
||||
@ -1182,7 +1178,7 @@
|
||||
|
||||
let tempData
|
||||
async function routeTo(targetPage, options = {}) {
|
||||
const { firstLoad, hashChange } = options
|
||||
const { firstLoad, hashChange, smartContractsUnavailable = false } = options
|
||||
let pageId
|
||||
let params = {}
|
||||
let searchParams
|
||||
@ -1233,6 +1229,10 @@
|
||||
case 'smartcontracts':
|
||||
const [subpage] = wildcards
|
||||
const { type, subtype, scName, scAddress } = params
|
||||
if (smartContractsUnavailable) {
|
||||
notify('Smart contracts are currently unavailable, please try again later.', 'error')
|
||||
return
|
||||
}
|
||||
if (subpage) {
|
||||
switch (subpage) {
|
||||
case 'create':
|
||||
@ -1242,34 +1242,13 @@
|
||||
getRef('smart_contract_creation_form').classList.remove('split-layout')
|
||||
renderElem(getRef('smart_contract_creation_form'), render.contractCreationForm(type, subtype))
|
||||
getRef('smart_contract_creation_form').querySelectorAll('[data-flo-address]').forEach(input => {
|
||||
input.customValidation = floCrypto.validateFloID
|
||||
input.customValidation = (value) => {
|
||||
return {
|
||||
isValid: floCrypto.validateAddr(value),
|
||||
errorText: `Invalid FLO address.<br> It usually starts with "F".`
|
||||
}
|
||||
}
|
||||
})
|
||||
switch (type) {
|
||||
case 'one-time-event':
|
||||
switch (subtype) {
|
||||
case 'time-trigger':
|
||||
const payeeAddressObserver = new MutationObserver((mutations) => {
|
||||
mutations.forEach((mutation) => {
|
||||
if (mutation.type === 'childList') {
|
||||
if (mutation.addedNodes.length) {
|
||||
|
||||
}
|
||||
if (mutation.removedNodes.length) {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
payeeAddressObserver.observe(document.getElementById('payee_container'), { childList: true });
|
||||
break;
|
||||
case 'external-trigger':
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'continuous-event':
|
||||
|
||||
break;
|
||||
}
|
||||
showChildElement('smartcontracts', 1, { entry: slideInLeft, exit: slideOutLeft })
|
||||
break;
|
||||
case 'deposit': {
|
||||
@ -1279,7 +1258,7 @@
|
||||
if (scName && scAddress)
|
||||
selectedSmartContract = getScDetails(scName, scAddress)
|
||||
const { price, contractName, contractAddress, acceptingToken, sellingToken, tokenIdentification, contractSubType } = selectedSmartContract
|
||||
history.replaceState(null, null, `#/smartcontracts/deposit?scName=${contractName}&scAddress=${contractAddress}`)
|
||||
history.replaceState(null, null, `#/smartcontracts/${subpage}?scName=${contractName}&scAddress=${contractAddress}`)
|
||||
const defaultExpiration = new Date(new Date().getTime() + (floGlobals.expirationDays * 24 * 60 * 60 * 1000))
|
||||
.toISOString().slice(0, -8);
|
||||
renderElem(getRef('smart_contract_deposit_form'), html`
|
||||
@ -1334,7 +1313,7 @@
|
||||
if (scName && scAddress)
|
||||
selectedSmartContract = getScDetails(scName, scAddress)
|
||||
const { price, contractName, contractAddress, acceptingToken, sellingToken, tokenIdentification, userChoices, contractSubType } = selectedSmartContract
|
||||
history.replaceState(null, null, `#/smartcontracts/participate?scName=${contractName}&scAddress=${contractAddress}`)
|
||||
history.replaceState(null, null, `#/smartcontracts/${subpage}?scName=${contractName}&scAddress=${contractAddress}`)
|
||||
renderElem(getRef('smart_contract_participate_form'), html`
|
||||
<div class="grid gap-0-5">
|
||||
<span class="label">Select smart contract</span>
|
||||
@ -1396,7 +1375,7 @@
|
||||
if (scName && scAddress)
|
||||
selectedSmartContract = getScDetails(scName, scAddress)
|
||||
const { contractName, contractAddress, oracle_address, price, acceptingToken } = selectedSmartContract
|
||||
history.replaceState(null, null, `#/smartcontracts/participate?scName=${contractName}&scAddress=${contractAddress}`)
|
||||
history.replaceState(null, null, `#/smartcontracts/${subpage}?scName=${contractName}&scAddress=${contractAddress}`)
|
||||
renderElem(getRef('smart_contract_update_form'), html`
|
||||
<div class="grid gap-0-5">
|
||||
<span class="label">Oracle FLO Address</span>
|
||||
@ -1448,7 +1427,7 @@
|
||||
if (scName && scAddress)
|
||||
selectedSmartContract = getScDetails(scName, scAddress)
|
||||
const { contractName, contractAddress, price, tokenIdentification, userChoices } = selectedSmartContract
|
||||
history.replaceState(null, null, `#/smartcontracts/trigger?scName=${contractName}&scAddress=${contractAddress}`)
|
||||
history.replaceState(null, null, `#/smartcontracts/${subpage}?scName=${contractName}&scAddress=${contractAddress}`)
|
||||
renderElem(getRef('smart_contract_trigger_form'), html`
|
||||
<div class="grid gap-0-5">
|
||||
<span class="label">Select smart contract</span>
|
||||
@ -1468,7 +1447,7 @@
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="grid gap-0-5">
|
||||
<span class="label">Contract address FLO private key</span>
|
||||
<span class="label">Committee address FLO private key</span>
|
||||
<sm-input id="trigger_private_key" class="password-field" type="password" error-text="Invalid private key" data-private-key="" required="">
|
||||
<label slot="right" class="interact">
|
||||
<input type="checkbox" class="hidden" readonly="" onchange="togglePrivateKeyVisibility(this)">
|
||||
@ -1501,12 +1480,40 @@
|
||||
}
|
||||
break
|
||||
}
|
||||
let previousActiveElement = getRef('main_navbar').querySelector('.nav-item--active')
|
||||
const currentActiveElement = document.querySelector(`.nav-item[href="#/${pageId}"]`)
|
||||
if (document.startViewTransition) {
|
||||
document.startViewTransition(() => {
|
||||
if (previousActiveElement) {
|
||||
previousActiveElement.classList.remove('nav-item--active');
|
||||
previousActiveElement.querySelector('.nav-item__indicator')?.remove()
|
||||
}
|
||||
if (currentActiveElement) {
|
||||
if (getRef('main_navbar').classList.contains('hidden')) {
|
||||
getRef('main_navbar').classList.remove('hide-away')
|
||||
getRef('main_navbar').classList.remove('hidden')
|
||||
}
|
||||
getRef('main_header').classList.remove('hidden')
|
||||
currentActiveElement.classList.add('nav-item--active')
|
||||
currentActiveElement.append(createElement('div', { className: 'nav-item__indicator' }));
|
||||
} else {
|
||||
if (!getRef('main_navbar').classList.contains('hidden')) {
|
||||
getRef('main_navbar').classList.add('hide-away')
|
||||
getRef('main_navbar').classList.add('hidden')
|
||||
getRef('main_header').classList.add('hidden')
|
||||
}
|
||||
}
|
||||
if (pagesData.lastPage !== pageId) {
|
||||
document.querySelectorAll('.page').forEach(page => page.classList.add('hidden'))
|
||||
getRef(pageId).classList.remove('hidden')
|
||||
pagesData.lastPage = pageId
|
||||
}
|
||||
})
|
||||
} else {
|
||||
const animOptions = {
|
||||
duration: 100,
|
||||
fill: 'forwards',
|
||||
}
|
||||
let previousActiveElement = getRef('main_navbar').querySelector('.nav-item--active')
|
||||
const currentActiveElement = document.querySelector(`.nav-item[href="#/${pageId}"]`)
|
||||
if (currentActiveElement) {
|
||||
if (getRef('main_navbar').classList.contains('hidden')) {
|
||||
getRef('main_navbar').classList.remove('hide-away')
|
||||
@ -1596,8 +1603,19 @@
|
||||
getRef(pageId).animate([{ opacity: 0 }, { opacity: 1 }], { duration: 300, fill: 'forwards', easing: 'ease' })
|
||||
pagesData.lastPage = pageId
|
||||
}
|
||||
document.querySelectorAll('sm-input[data-flo-address]').forEach(input => input.customValidation = floCrypto.validateFloID)
|
||||
document.querySelectorAll('sm-input[data-private-key]').forEach(input => input.customValidation = floCrypto.getPubKeyHex)
|
||||
}
|
||||
document.querySelectorAll('sm-input[data-flo-address]').forEach(input => input.customValidation = (value) => {
|
||||
return {
|
||||
isValid: floCrypto.validateAddr(value),
|
||||
errorText: `Invalid FLO address.<br> It usually starts with "F"`
|
||||
}
|
||||
})
|
||||
document.querySelectorAll('sm-input[data-private-key]').forEach(input => input.customValidation = (value) => {
|
||||
return {
|
||||
isValid: floCrypto.getPubKeyHex(value),
|
||||
errorText: `Invalid private key.<br> It's a long string of random characters usually starting with 'R'.`
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const indicatorObserver = new IntersectionObserver(entries => {
|
||||
@ -1718,7 +1736,7 @@
|
||||
handleMobileChange(mobileQuery)
|
||||
|
||||
// fetch data and return json
|
||||
async function fetchJSON(url, options = {}) {
|
||||
async function fetchJson(url, options = {}) {
|
||||
const response = await fetch(url, options)
|
||||
const json = await response.json()
|
||||
if (response.ok) {
|
||||
@ -1984,7 +2002,7 @@
|
||||
availableSmartContractOptions(smartContracts = [], selected) {
|
||||
return smartContracts
|
||||
.map(({ contractName, contractAddress }) => html`
|
||||
<sm-option class="breakable" value=${`${contractName}_${contractAddress}`} ?selected=${`${contractName}_${contractAddress}` === `${selected}`}>${`${replaceDash(contractName)} (${contractAddress})`}</sm-option>
|
||||
<sm-option class="breakable" value=${`${contractName}_${contractAddress}`} selected=${`${contractName}_${contractAddress}` === `${selected}`}>${`${replaceDash(contractName)} (${contractAddress})`}</sm-option>
|
||||
`)
|
||||
},
|
||||
contractCreationForm(type, subtype) {
|
||||
@ -2100,7 +2118,7 @@
|
||||
</div>
|
||||
<div class="grid gap-0-5">
|
||||
<span class="label">Price (1 deposit token = ? participation token)</span>
|
||||
<sm-input id="contract_initial_price" type="number" required> </sm-input>
|
||||
<sm-input id="contract_initial_price" type="number" step="0.00000001" min="0.00000001" required> </sm-input>
|
||||
</div>
|
||||
`}
|
||||
<div class="grid gap-0-5">
|
||||
@ -2314,7 +2332,7 @@
|
||||
const senderFloAddr = floCrypto.getFloID(senderPrivateKey)
|
||||
Promise.all([
|
||||
floWebWallet.getBalance(senderFloAddr),
|
||||
fetchJSON(`${floGlobals.tokenApiUrl}/api/v2/floAddressBalance/${senderFloAddr}`)
|
||||
fetchJson(`${floGlobals.tokenApiUrl}/api/v2/floAddressBalance/${senderFloAddr}`)
|
||||
]).then(([retrievedBal, { floAddressBalances }]) => {
|
||||
renderBalance({ balance: parseFloat(retrievedBal), address: senderFloAddr })
|
||||
let ownedTokens = []
|
||||
@ -2531,7 +2549,7 @@
|
||||
getRef('flo_balance').innerHTML = `<sm-spinner></sm-spinner>`;
|
||||
const [floBalance, tokenBalances] = await Promise.all([
|
||||
floWebWallet.getBalance(queriedFloId),
|
||||
fetchJSON(`${floGlobals.tokenApiUrl}/api/v2/floAddressBalance/${queriedFloId}`).then(({ floAddressBalances }) => floAddressBalances)
|
||||
fetchJson(`${floGlobals.tokenApiUrl}/api/v2/floAddressBalance/${queriedFloId}`).then(({ floAddressBalances }) => floAddressBalances)
|
||||
])
|
||||
let ownedTokens = []
|
||||
for (const token in tokenBalances) {
|
||||
@ -2817,7 +2835,7 @@
|
||||
name = floGlobals.smartContracts[0].contractName
|
||||
address = floGlobals.smartContracts[0].contractAddress
|
||||
}
|
||||
fetchJSON(`${floGlobals.tokenApiUrl}/api/v2/smartContractInfo?contractName=${name}&contractAddress=${address}`)
|
||||
fetchJson(`${floGlobals.tokenApiUrl}/api/v2/smartContractInfo?contractName=${name}&contractAddress=${address}`)
|
||||
.then(info => {
|
||||
console.log(info)
|
||||
const {
|
||||
@ -2878,17 +2896,23 @@
|
||||
}
|
||||
|
||||
function filterSmartContracts(options) {
|
||||
const { type, subType, dynamic = false } = options || {}
|
||||
let filteredSmartContracts = (floGlobals.smartContracts || [])
|
||||
.filter(sc => sc.status === 'active')
|
||||
const { type, subType, dynamic = false } = options || {};
|
||||
let filteredSmartContracts = floGlobals.smartContracts || [];
|
||||
if (type) {
|
||||
filteredSmartContracts = filteredSmartContracts.filter(sc => sc.contractType === type)
|
||||
if (type === 'continuos-event' && dynamic)
|
||||
filteredSmartContracts = filteredSmartContracts.filter(sc => sc.oracle_address)
|
||||
filteredSmartContracts = filteredSmartContracts.filter(sc => {
|
||||
if (subType && subType === 'external-trigger') {
|
||||
return sc.status === 'expired'; // only inactive contracts can be triggered externally
|
||||
} else if (type === 'continuos-event' && dynamic) {
|
||||
return sc.status === 'active' && sc.contractType === type && sc.oracle_address;
|
||||
} else {
|
||||
return sc.status === 'active' && sc.contractType === type;
|
||||
}
|
||||
if (subType)
|
||||
filteredSmartContracts = filteredSmartContracts.filter(sc => sc.contractSubType === subType)
|
||||
return filteredSmartContracts
|
||||
});
|
||||
}
|
||||
if (subType) {
|
||||
filteredSmartContracts = filteredSmartContracts.filter(sc => sc.contractSubType === subType);
|
||||
}
|
||||
return filteredSmartContracts;
|
||||
}
|
||||
|
||||
function handleSmartContractSelection(actionType) {
|
||||
@ -3018,6 +3042,7 @@
|
||||
const [contractName, contractAddress] = (selectedSmartContract).split('_')
|
||||
const oraclePrivateKey = document.getElementById('oracle_private_key').value.trim()
|
||||
const oracleAddress = document.getElementById('oracle_address').value
|
||||
const { acceptingToken } = getScDetails(contractName, contractAddress)
|
||||
if (!floCrypto.verifyPrivKey(oraclePrivateKey, oracleAddress)) {
|
||||
return notify(`Private key doesn't match with Oracle address`, 'error')
|
||||
}
|
||||
@ -3025,7 +3050,7 @@
|
||||
const floData = ` {"price-update":{"contract-name": "${contractName}", "contract-address": "${contractAddress}", "price": ${updatedPrice}}} `
|
||||
console.log(floData)
|
||||
getConfirmation('Update price', {
|
||||
message: `Are you sure you want to update the price of ${contractName} to ${updatedPrice} FLO?`,
|
||||
message: `Are you sure you want to update the price of ${contractName} to ${updatedPrice} ${acceptingToken}?`,
|
||||
confirmText: 'Update',
|
||||
cancelText: 'Cancel'
|
||||
}).then((res) => {
|
||||
@ -3054,9 +3079,9 @@
|
||||
const triggerOutcome = getRef('smart_contract_trigger_form').querySelector('input[name="outcome"]:checked').value
|
||||
const floData = `${contractName}@ triggerCondition:"${triggerOutcome}"`
|
||||
console.log(floData)
|
||||
if (contractAddress !== triggerAddress) {
|
||||
return notify(`Private key doesn't match with contract trigger address`, 'error')
|
||||
}
|
||||
// if (contractAddress !== triggerAddress) {
|
||||
// return notify(`Private key doesn't match with contract trigger address`, 'error')
|
||||
// }
|
||||
getConfirmation('Trigger contract', {
|
||||
message: `Triggering ${contractName} with outcome: ${triggerOutcome}`,
|
||||
confirmText: 'Trigger',
|
||||
@ -3064,7 +3089,7 @@
|
||||
}).then((res) => {
|
||||
if (!res) return
|
||||
buttonLoader('trigger_contract_button', true)
|
||||
floBlockchainAPI.writeData(contractAddress, floData, triggerPrivateKey, contractAddress).then((txid) => {
|
||||
floBlockchainAPI.writeData(triggerAddress, floData, triggerPrivateKey, contractAddress).then((txid) => {
|
||||
showTransactionResult(true, txid, {
|
||||
title: 'Contract trigger initiated',
|
||||
})
|
||||
@ -3113,13 +3138,22 @@
|
||||
return notify(`Contract expiration datetime cannot be in the past`, 'error')
|
||||
}
|
||||
const contractParticipationAmount = parseFloat(document.getElementById('contract_participation_amount').value.trim()) || 0;
|
||||
const contractMinSubAmount = parseFloat(document.getElementById('contract_min_sub_amount').value.trim()) || 0;
|
||||
const contractMaxSubAmount = parseFloat(document.getElementById('contract_max_sub_amount').value.trim()) || 0;
|
||||
if (contractMinSubAmount > contractMaxSubAmount) {
|
||||
const contractMinSubAmount = parseFloat(document.getElementById('contract_min_sub_amount').value.trim());
|
||||
const contractMaxSubAmount = parseFloat(document.getElementById('contract_max_sub_amount').value.trim());
|
||||
if (contractMinSubAmount && contractMaxSubAmount && contractMinSubAmount > contractMaxSubAmount) {
|
||||
return notify(`Contract minimum subscription amount cannot be greater than maximum subscription amount`, 'error')
|
||||
}
|
||||
const contractConditions = {}
|
||||
if (contractExpiration)
|
||||
contractConditions.expiryTime = new Date(contractExpiration).toString()
|
||||
if (contractParticipationAmount)
|
||||
contractConditions.contractamount = contractParticipationAmount
|
||||
if (contractMinSubAmount)
|
||||
contractConditions.minimumsubscriptionamount = contractMinSubAmount
|
||||
if (contractMaxSubAmount)
|
||||
contractConditions.maximumsubscriptionamount = contractMaxSubAmount
|
||||
switch (subtype) {
|
||||
case 'time-trigger':
|
||||
case 'time-trigger': {
|
||||
const payeeAddressesShare = {}
|
||||
document.querySelectorAll('.payee-address-wrapper').forEach((payeeAddressWrapper) => {
|
||||
const payeeAddress = payeeAddressWrapper.querySelector('.payee-address').value.trim()
|
||||
@ -3153,27 +3187,35 @@
|
||||
return notify(`Total share cannot be greater than 100`, 'error')
|
||||
}
|
||||
const payeeAddressesShareString = Object.entries(payeeAddressesShare).map(([payeeAddress, payeeShare]) => `${payeeAddress}:${payeeShare}`).join(':')
|
||||
console.log(payeeAddressesShareString)
|
||||
floData = `Create a smart contract of the name ${contractName}@ of the type one-time-event* using asset ${contractAsset}# at the FLO address ${creatorAddress}$ with contract-conditions: (1) expiryTime= ${new Date(contractExpiration).toString()} (2) payeeAddress= ${payeeAddressesShareString} ${contractParticipationAmount ? `(3) contractamount = ${contractParticipationAmount}` : ''} ${contractMinSubAmount ? `(4) minimumsubscriptionamount = ${contractMinSubAmount}` : ''} ${contractMaxSubAmount ? `(5) maximumsubscriptionamount = ${contractMaxSubAmount}` : ''} end-contract-conditions`
|
||||
|
||||
if (payeeAddressesShareString)
|
||||
contractConditions.payeeAddress = payeeAddressesShareString
|
||||
const contractConditionsString = Object.entries(contractConditions).map(([key, value], index) => `(${index + 1}) ${key}= ${value}`).join(' ')
|
||||
floData = `Create a smart contract of the name ${contractName}@ of the type one-time-event* using asset ${contractAsset}# at the FLO address ${creatorAddress}$ with contract-conditions: ${contractConditionsString} end-contract-conditions`
|
||||
if (floData.length > 1040) return notify(`Too many payee addresses! remove some and try again`, 'error')
|
||||
confirmationMessage = `Name: ${contractName} \nType: One-time event \nSubtype: Time trigger \nAsset: ${contractAsset} \nExpiration: ${new Date(contractExpiration).toString()} \nPayee addresses: ${Object.entries(payeeAddressesShare).reduce((str, [address, share]) => `${address}: ${share}%`, '')} \nParticipation amount: ${contractParticipationAmount} ${contractAsset} \nMin subscription amount: ${contractMinSubAmount} ${contractAsset} \nMax subscription amount: ${contractMaxSubAmount} ${contractAsset}`
|
||||
break;
|
||||
case 'external-trigger':
|
||||
// add confirmation message with contract details only if they are defined
|
||||
confirmationMessage = `Name: ${contractName} \nType: One time event \nSubtype: Time trigger \nAsset: ${contractAsset} \nExpiration: ${new Date(contractExpiration).toString()} \nPayee addresses: ${payeeAddressesShareString} ${contractParticipationAmount ? `\nParticipation amount: ${contractParticipationAmount} ${contractAsset}` : ''} ${contractMinSubAmount ? `\nMinimum subscription amount: ${contractMinSubAmount} ${contractAsset}` : ''} ${contractMaxSubAmount ? `\nMaximum subscription amount: ${contractMaxSubAmount} ${contractAsset}` : ''}`
|
||||
} break;
|
||||
case 'external-trigger': {
|
||||
const userChoices = new Set()
|
||||
document.querySelectorAll('.user-choice').forEach((userChoice) => {
|
||||
const userChoiceValue = userChoice.value.trim()
|
||||
if (userChoiceValue !== '')
|
||||
userChoices.add(userChoiceValue)
|
||||
})
|
||||
floData = `Create a smart contract of the name ${contractName}@ of the type one-time-event* using asset ${contractAsset}# at the FLO address ${creatorAddress}$ with contract-conditions:(1) expiryTime= ${new Date(contractExpiration).toString()} (2) userchoices= ${[...userChoices].join(' | ')} ${contractParticipationAmount ? `(3) contractamount = ${contractParticipationAmount}` : ''} ${contractMinSubAmount ? `(4) minimumsubscriptionamount = ${contractMinSubAmount}` : ''} ${contractMaxSubAmount ? `(5) maximumsubscriptionamount = ${contractMaxSubAmount}` : ''} end-contract-conditions`
|
||||
if (userChoices.size)
|
||||
contractConditions.userchoices = [...userChoices].join(' | ')
|
||||
const contractConditionsString = Object.entries(contractConditions).map(([key, value], index) => `(${index + 1}) ${key}= ${value}`).join(' ')
|
||||
floData = `Create a smart contract of the name ${contractName}@ of the type one-time-event* using asset ${contractAsset}# at the FLO address ${creatorAddress}$ with contract-conditions:${contractConditionsString} end-contract-conditions`
|
||||
if (floData.length > 1040) return notify(`Too many participant choices! remove some and try again`, 'error')
|
||||
confirmationMessage = `Name: ${contractName} \nType: One-time event \nSubtype: External trigger \nAsset: ${contractAsset} \nExpiration: ${new Date(contractExpiration).toString()} \nParticipant choices: ${[...userChoices].join(' | ')} \nParticipation amount: ${contractParticipationAmount} ${contractAsset} \nMin subscription amount: ${contractMinSubAmount} ${contractAsset} \nMax subscription amount: ${contractMaxSubAmount} ${contractAsset}`
|
||||
break;
|
||||
// add confirmation message with contract details only if they are defined
|
||||
confirmationMessage = `Name: ${contractName} \nType: One time event \nSubtype: External trigger \nAsset: ${contractAsset} \nExpiration: ${new Date(contractExpiration).toString()} \nUser choices: ${[...userChoices].join(' | ')} ${contractParticipationAmount ? `\nParticipation amount: ${contractParticipationAmount} ${contractAsset}` : ''} ${contractMinSubAmount ? `\nMinimum subscription amount: ${contractMinSubAmount} ${contractAsset}` : ''} ${contractMaxSubAmount ? `\nMaximum subscription amount: ${contractMaxSubAmount} ${contractAsset}` : ''}`
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
case 'continuous-event':
|
||||
switch (subtype) {
|
||||
case 'tokenswap':
|
||||
case 'tokenswap': {
|
||||
const priceType = document.querySelector('input[name="price-type"]:checked').value
|
||||
const participationToken = document.getElementById('contract_input_token').value
|
||||
const depositToken = document.getElementById('contract_output_token').value
|
||||
@ -3184,7 +3226,7 @@
|
||||
oracleAddress = document.getElementById('contract_oracle_address').value.trim()
|
||||
floData = `Create Smart Contract with the name ${contractName}@ of the type continuous-event* at the address ${creatorAddress}$ with contract-conditions : (1) subtype = tokenswap (2) accepting_token = ${participationToken}# (3) selling_token = ${depositToken}# (4) price = '${initialPrice}' (5) priceType = ${priceType} ${oracleAddress ? `(6) oracle_address = ${oracleAddress}` : ''} end-contract-conditions`
|
||||
confirmationMessage = `Name: ${contractName} \nType: Continuous event \nSubtype: Token swap \nDeposit token: ${depositToken} \nParticipation token: ${participationToken} \nInitial price: ${initialPrice} ${participationToken} per ${depositToken} \nPrice type: ${priceType} ${oracleAddress ? `\nOracle address: ${oracleAddress}` : ''}`
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -3226,7 +3268,12 @@
|
||||
document.getElementById('payee_container').querySelectorAll('.payee-share').forEach((input) => {
|
||||
input.value = parseFloat((100 / document.getElementById('payee_container').querySelectorAll('.payee-share').length).toFixed(2))
|
||||
})
|
||||
document.getElementById('payee_container').lastElementChild.querySelector('.payee-address').customValidation = floCrypto.validateFloID
|
||||
document.getElementById('payee_container').lastElementChild.querySelector('.payee-address').customValidation = (value) => {
|
||||
return {
|
||||
isValid: floCrypto.validateAddr(value),
|
||||
errorText: `Invalid FLO address.<br> It usually starts with "F".`
|
||||
}
|
||||
}
|
||||
}
|
||||
function removePayee(e) {
|
||||
e.target.closest('li').remove()
|
||||
@ -3270,7 +3317,6 @@
|
||||
function replaceDash(str) {
|
||||
return str.replace(/-/g, ' ')
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -7,7 +7,7 @@
|
||||
blockchain: floGlobals.blockchain,
|
||||
apiURL: {
|
||||
FLO: ['https://blockbook.ranchimall.net/'],
|
||||
FLO_TEST: []
|
||||
FLO_TEST: ['https://blockbook-testnet.ranchimall.net/']
|
||||
},
|
||||
sendAmt: 0.0003,
|
||||
fee: 0.0002,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user