Skip to content

Commit

Permalink
feature: adds neo legacy test net support / migration support (#2177)
Browse files Browse the repository at this point in the history
* Sets up foundation for migration with working legacy testnet support

* lint

* Fix activity history

* lint

* Update snaps

* Additional testnet support

* lint

* TestNet and explorer linking enhancements

* A working migration implementation on testnet

* Mint CGAS if below threshold

* Adds error handling and UX goodies

* Update snaps

* Working on mainnet

* lint

* Ready for test build

* updates copy for migration workflow

* adds migration tracker remark

* Bump version and update snapshots

* lint

* update node list

* Fixes remaining defects

* Update snaps

Co-authored-by: lllwvlvwlll <lllwvlvwlll@gmail.com>
  • Loading branch information
comountainclimber and lllwvlvwlll authored Aug 24, 2021
1 parent 982cc1a commit d45596d
Show file tree
Hide file tree
Showing 76 changed files with 3,120 additions and 179 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@
"flowtype/generic-spacing": 0,
"no-param-reassign": ["warn"],
"no-restricted-syntax": ["error", "LabeledStatement", "WithStatement"],
"no-await-in-loop": 0
"no-await-in-loop": 0,
"jsx-a11y/alt-text": 0
},
"settings": {
"import/resolver": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ exports[`ConfirmModal should render without crashing 1`] = `
width="500px"
>
<Connect(withData(BaseModal))
hideModal={[MockFunction]}
hideModal={[Function]}
shouldRenderHeader={false}
style={
Object {
"content": Object {
"height": "200px",
"height": "250px",
"width": "500px",
},
}
Expand All @@ -38,13 +38,13 @@ exports[`ConfirmModal should render without crashing 1`] = `
backButtonAction={null}
dispatch={[Function]}
height="450px"
hideModal={[MockFunction]}
hideModal={[Function]}
shouldCloseWithEscapeKey={true}
shouldRenderHeader={false}
style={
Object {
"content": Object {
"height": "200px",
"height": "250px",
"width": "500px",
},
}
Expand Down Expand Up @@ -201,7 +201,7 @@ exports[`ConfirmModal should render without crashing 1`] = `
"color": "var(--base-text)",
"display": "flex",
"flexDirection": "column",
"height": "200px",
"height": "250px",
"margin": "auto",
"padding": 0,
"width": "500px",
Expand Down Expand Up @@ -352,7 +352,7 @@ exports[`ConfirmModal should render without crashing 1`] = `
>
<div
class="ReactModal__Content ReactModal__Content--after-open"
style="position: absolute; top: 40px; left: 40px; right: 40px; bottom: 40px; overflow: auto; border-radius: 4px; outline: none; padding: 0px; width: 500px; height: 200px; margin: auto; box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 4px; display: flex; flex-direction: column; z-index: 5000;"
style="position: absolute; top: 40px; left: 40px; right: 40px; bottom: 40px; overflow: auto; border-radius: 4px; outline: none; padding: 0px; width: 500px; height: 250px; margin: auto; box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 4px; display: flex; flex-direction: column; z-index: 5000;"
tabindex="-1"
>
<div
Expand Down Expand Up @@ -573,7 +573,7 @@ exports[`ConfirmModal should render without crashing 1`] = `
"color": "var(--base-text)",
"display": "flex",
"flexDirection": "column",
"height": "200px",
"height": "250px",
"margin": "auto",
"padding": 0,
"width": "500px",
Expand Down Expand Up @@ -1000,7 +1000,7 @@ exports[`ConfirmModal should render without crashing 1`] = `
"color": "var(--base-text)",
"display": "flex",
"flexDirection": "column",
"height": "200px",
"height": "250px",
"left": "40px",
"margin": "auto",
"outline": "none",
Expand Down
2 changes: 1 addition & 1 deletion __tests__/components/__snapshots__/Settings.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,7 @@ exports[`Settings renders without crashing 1`] = `
Manage your neon wallet
</FormattedMessage>
- v
2.7.4
2.8.0
</div>
<div
className="settingsPanelHeaderItem"
Expand Down
34 changes: 34 additions & 0 deletions __tests__/components/__snapshots__/Sidebar.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,40 @@ exports[`Sidebar renders without crashing 1`] = `
</Link>
</Route>
</NavLink>
<NavLink
activeClassName="active"
aria-current="page"
className="navItem migration"
id="migration"
to="/migration"
>
<Route
path="\\\\/migration"
>
<Link
aria-current={null}
className="navItem migration"
id="migration"
replace={false}
to="/migration"
>
<a
aria-current={null}
className="navItem migration"
href="/migration"
id="migration"
onClick={[Function]}
>
<Component>
<svg />
</Component>
<div>
Migration
</div>
</a>
</Link>
</Route>
</NavLink>
</div>
<Connect(withActions(Connect(withActions(Logout))))
className="group logoutToolTipGroup navItem"
Expand Down
52 changes: 49 additions & 3 deletions app/actions/balancesActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { rpc as n3Rpc } from '@cityofzion/neon-js-next'
import { extend, isEmpty, get } from 'lodash-es'
import { createActions } from 'spunky'
import { Howl } from 'howler'
import axios from 'axios'

// $FlowFixMe
import coinAudioSample from '../assets/audio/coin.wav'

Expand Down Expand Up @@ -282,16 +284,60 @@ async function getBalances({ net, address, isRetry = false, chain }: Props) {
.getBalanceFrom({ net, address }, api.neoscan)
.catch(e => console.error(e))

const assets = get(assetBalances, 'balance.assets', {})
const testnetBalances = await axios.get(
`https://dora.coz.io/api/v1/neo2/testnet/get_balance/${address}`,
)
const parsedTestNetBalances = {}

testnetBalances.data.balance.forEach(token => {
parsedTestNetBalances[token.asset_symbol || token.symbol] = {
balance: token.amount,
hash: token.asset_hash,
}
})

const assets =
net === 'MainNet'
? get(assetBalances, 'balance.assets', {})
: parsedTestNetBalances

// The API doesn't always return NEO or GAS keys if, for example, the address only has one asset
const neoBalance = assets.NEO ? assets.NEO.balance.toString() : '0'
// eslint-disable-next-line
const neoBalance = assets.NEO
? net === 'MainNet'
? assets.NEO.balance.toString()
: assets.NEO.balance
: '0'
// eslint-disable-next-line
const gasBalance = assets.GAS
? assets.GAS.balance.round(COIN_DECIMAL_LENGTH).toString()
? net === 'MainNet'
? assets.GAS.balance.round(COIN_DECIMAL_LENGTH).toString()
: assets.GAS.balance
: '0'

const parsedAssets = [
{ [ASSETS.NEO]: neoBalance },
{ [ASSETS.GAS]: gasBalance },
]

if (net === 'TestNet') {
Object.keys(parsedTestNetBalances).map(sym => {
const balance = {
[parsedTestNetBalances[sym].hash]: {
balance: toBigNumber(parsedTestNetBalances[sym].balance),
symbol: sym,
networkId: '2',
scriptHash: parsedTestNetBalances[sym].hash,
},
}
if (sym !== 'GAS' && sym !== 'NEO') {
return parsedAssets.push(balance)
}

return null
})
}

determineIfBalanceUpdated(
{ [ASSETS.NEO]: neoBalance },
soundEnabled,
Expand Down
2 changes: 2 additions & 0 deletions app/actions/blockHeightActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ export const ID = 'blockHeight'

export const getBlockHeight = async (networkId: string) => {
let url = await getNode(networkId)

if (isEmpty(url)) {
url = await getRPCEndpoint(networkId)
}

const client = new rpc.RPCClient(url)
const count = await client.getBlockCount()
return count
Expand Down
10 changes: 10 additions & 0 deletions app/actions/newMigrationWalletActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// @flow
import { createActions } from 'spunky'

export const ID = 'migration'

type Props = {
name: string,
}

export default createActions(ID, ({ name }: Props = {}) => () => name)
1 change: 1 addition & 0 deletions app/actions/nodeNetworkActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export default createActions(ID, ({ networkId }) => async () => {
data =>
!NODE_EXLUSION_CRITERIA.some(criteria => data.url.includes(criteria)),
)

if (chain === 'neo2') {
switch (networkId) {
case MAIN_NETWORK_ID:
Expand Down
6 changes: 6 additions & 0 deletions app/actions/nodeStorageActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ type Props = {
net: Net,
}

export const resetCachedNode = () => {
delete cachedRPCUrl.MainNet
delete cachedRPCUrl.TestNet
}

export const determineIfCacheIsExpired = (
timestamp: number,
expiration: number = CACHE_EXPIRATION,
Expand Down Expand Up @@ -159,6 +164,7 @@ export const getNode = async (
if (!nodeInStorage || !expiration || determineIfCacheIsExpired(expiration)) {
return ''
}

return nodeInStorage
}

Expand Down
3 changes: 1 addition & 2 deletions app/actions/settingsActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,12 @@ export const updateSettingsActions = createActions(
// $FlowFixMe
(values: Settings = {}) => async (): Promise<Settings> => {
const settings = await getSettings()
const { chain } = settings
const { chain } = values
const newSettings = {
...settings,
...values,
}
const parsedForLocalStorage = cloneDeep(newSettings)

if (chain === 'neo2') {
const tokensForStorage = [
...newSettings.tokens.filter(token => token.isUserGenerated),
Expand Down
21 changes: 20 additions & 1 deletion app/actions/transactionHistoryActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { createActions } from 'spunky'
import { TX_TYPES } from '../core/constants'
import { findAndReturnTokenInfo } from '../util/findAndReturnTokenInfo'
import { getSettings } from './settingsActions'
import { toBigNumber } from '../core/math'

type Props = {
net: string,
Expand All @@ -30,6 +31,7 @@ export async function parseAbstractData(

const parsedTo = abstract => {
if (abstract.address_to === 'fees') return 'NETWORK FEES'
if (abstract.address_to === 'fee') return 'NETWORK FEES'
if (abstract.address_to === 'mint') return 'MINT TOKENS'
return abstract.address_to
}
Expand All @@ -50,7 +52,7 @@ export async function parseAbstractData(
from: parsedFrom(abstract),
txid: abstract.txid,
time: abstract.time,
amount: abstract.amount,
amount: toBigNumber(abstract.amount).toString(),
asset,
symbol: asset.symbol,
image: asset.image,
Expand Down Expand Up @@ -96,6 +98,23 @@ export default createActions(
}/get_address_abstracts/${address}/${page}`,
)

// eslint-disable-next-line
data = results.data
} else if (net === 'TestNet' && chain === 'neo2') {
const results = await axios.get(
`https://dora.coz.io/api/v1/neo2/testnet/get_address_abstracts/${address}/${page}`,
)
results.data.entries = results.data.entries.map(entry => {
const parsedEntry = { ...entry }
if (
entry.asset ===
'602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7'
) {
parsedEntry.amount = entry.amount * 100000000
}

return parsedEntry
})
// eslint-disable-next-line
data = results.data
} else {
Expand Down
9 changes: 9 additions & 0 deletions app/assets/icons/clock.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions app/assets/images/release-assets/migration-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions app/assets/images/release-assets/migration-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions app/assets/navigation/migration.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit d45596d

Please sign in to comment.