From 0c24a4419f41f4d72e252eb75f8ab66a164867c8 Mon Sep 17 00:00:00 2001 From: Matt Holtzman Date: Thu, 24 Feb 2022 14:10:25 -0500 Subject: [PATCH] URI encode calls to proxy, update usage of Opensea API (#749) * URI encode calls to proxy, update usage of Opensea API * cleanup * Improve inventory display and linking * Update valid host check Co-authored-by: Jordan Muir --- app/App/Panel/Main/Account/Balances/index.js | 2 +- app/App/Panel/Main/Account/Inventory/index.js | 38 +++++++++-- .../Main/Account/Inventory/style/index.styl | 3 + app/App/Panel/Main/Account/index.js | 28 ++++++-- app/App/Panel/Main/Signer/index.js | 2 +- app/App/Panel/Notify/CustomTokens/index.js | 2 +- app/App/Panel/Notify/index.js | 3 +- app/App/Panel/Notify/style/index.styl | 13 ++++ main/externalData/inventory/index.ts | 68 +++++++++++-------- main/index.js | 6 +- 10 files changed, 119 insertions(+), 46 deletions(-) diff --git a/app/App/Panel/Main/Account/Balances/index.js b/app/App/Panel/Main/Account/Balances/index.js index f403419a4..f4af00a9c 100644 --- a/app/App/Panel/Main/Account/Balances/index.js +++ b/app/App/Panel/Main/Account/Balances/index.js @@ -132,7 +132,7 @@ class Balances extends React.Component {
0 ? 1 : 0, transitionDelay: (0.1 * i) + 's' }}>
{symbol.toUpperCase()} diff --git a/app/App/Panel/Main/Account/Inventory/index.js b/app/App/Panel/Main/Account/Inventory/index.js index 7669ae574..74350f363 100644 --- a/app/App/Panel/Main/Account/Inventory/index.js +++ b/app/App/Panel/Main/Account/Inventory/index.js @@ -34,15 +34,36 @@ class Balances extends React.Component {
{'Inventory'} {this.props.expanded ? ( -
this.props.expandModule(false)}> +
{ + this.props.expandModule(false) + }}> {svg.close(12)}
) : null}
- {collections.length ? collections.map(k => { + {collections.length ? collections.filter(k => { + if (this.props.expanded) { + const expandedData = this.props.expandedData || {} + const current = expandedData.currentCollection + return current === k + } else { + return true + } + }).sort((a, b) => { + const assetsLengthA = Object.keys(inventory[a].assets).length + const assetsLengthB = Object.keys(inventory[b].assets).length + if (assetsLengthA > assetsLengthB) return -1 + if (assetsLengthA < assetsLengthB) return 1 + return 0 + }).map(k => { return ( -
this.props.expandModule(this.props.moduleId)}> +
{ + this.props.expandModule(this.props.moduleId, { currentCollection: k }) + }} + >
{inventory[k].meta.name}
{Object.keys(inventory[k].assets).length}
@@ -55,10 +76,15 @@ class Balances extends React.Component { b = inventory[k].assets[b].tokenId return a < b ? -1 : b > a ? 1 : 0 }).map(id => { - const { tokenId, name, img } = inventory[k].assets[id] + const { tokenId, name, img, openSeaLink } = inventory[k].assets[id] return ( -
- {img ? : null} +
{ + this.store.notify('openExternal', { url: openSeaLink }) + }} + > + {img ? : null}
) })} diff --git a/app/App/Panel/Main/Account/Inventory/style/index.styl b/app/App/Panel/Main/Account/Inventory/style/index.styl index 16b39cf39..2c2f87b1a 100644 --- a/app/App/Panel/Main/Account/Inventory/style/index.styl +++ b/app/App/Panel/Main/Account/Inventory/style/index.styl @@ -34,6 +34,8 @@ box-sizing border-box box-shadow 0px 4px 10px var(--ghostZ) cursor pointer + * + pointer-events none img width 100% @@ -47,6 +49,7 @@ right 16px bottom -1px border-bottom 1px solid var(--ghostA) + pointer-events none .inventoryCollectionName display flex diff --git a/app/App/Panel/Main/Account/index.js b/app/App/Panel/Main/Account/index.js index 624410e51..bdccd394b 100644 --- a/app/App/Panel/Main/Account/index.js +++ b/app/App/Panel/Main/Account/index.js @@ -188,7 +188,7 @@ class _AccountMain extends React.Component { // slideHeight += modulePositions[i].height // }) // } - renderModule (id, module, top, index, expandModule, expanded) { + renderModule (id, module, top, index, expandModule, expanded, expandedData) { // console.log(id, module, top, index) let hidden = false let style = { @@ -254,6 +254,7 @@ class _AccountMain extends React.Component { id={this.props.id} expandModule={expandModule} expanded={expanded} + expandedData={expandedData} /> : id === 'permissions' ? ) } + expandModule (id, data) { + this.setState({ expandedModule: id, expandedModuleData: data || {} }) + } render () { const accountModules = this.store('panel.account.modules') const accountModuleOrder = this.store('panel.account.moduleOrder') @@ -291,9 +295,13 @@ class _AccountMain extends React.Component { const modules = accountModuleOrder.map((id, i) => { const module = accountModules[id] || { height: 0 } slideHeight += module.height + 5 - return this.renderModule(id, module, slideHeight - module.height - 5, i, id => { - this.setState({ expandedModule: id }) - }) + return this.renderModule( + id, + module, + slideHeight - module.height - 5, + i, + this.expandModule.bind(this) + ) }) return (
@@ -306,9 +314,15 @@ class _AccountMain extends React.Component {
{ e.stopPropagation() }}> - {this.renderModule(this.state.expandedModule, { height: '100%' }, 0, 0, id => { - this.setState({ expandedModule: id }) - }, true)} + {this.renderModule( + this.state.expandedModule, + { height: '100%' }, + 0, + 0, + this.expandModule.bind(this), + true, + this.state.expandedModuleData + )}
) : null} diff --git a/app/App/Panel/Main/Signer/index.js b/app/App/Panel/Main/Signer/index.js index acb5242be..809f793ce 100644 --- a/app/App/Panel/Main/Signer/index.js +++ b/app/App/Panel/Main/Signer/index.js @@ -56,7 +56,7 @@ class _Balances extends React.Component { return (
this.setState({ selected: i })}>
- +
{token.symbol} diff --git a/app/App/Panel/Notify/CustomTokens/index.js b/app/App/Panel/Notify/CustomTokens/index.js index fc8cfe932..9d28f4e8b 100644 --- a/app/App/Panel/Notify/CustomTokens/index.js +++ b/app/App/Panel/Notify/CustomTokens/index.js @@ -38,7 +38,7 @@ class CustomTokens extends React.Component {
{token.symbol.toUpperCase()} diff --git a/app/App/Panel/Notify/index.js b/app/App/Panel/Notify/index.js index 55d20d168..936caad0a 100644 --- a/app/App/Panel/Notify/index.js +++ b/app/App/Panel/Notify/index.js @@ -444,7 +444,8 @@ class Notify extends React.Component { Open External Link
-
{`Frame will now open ${url} in your browser`}
+
{url}
+
{'Open Link in Browser?'}
{ + if (value) { + params.push([key, value].join('=')) + } + + return params + }, [] as string[]).join('&') + + const target = encodeURIComponent(`https://api.opensea.io/api/v1/assets?${queryStr}`) + const url = `https://proxy.pylon.link?type=api&target=${target}` const options = { method: 'GET', @@ -56,39 +74,33 @@ async function fetchAssets (address: Address, offset: number) { const errorMsg = contentType.includes('json') ? await res.json() : '' log.warn('unable to fetch inventory', errorMsg) - return { assets: [] } + return { assets: [], next: null, previous: null } } return res.json() as Promise } catch (e) { log.warn(`could not fetch assets ${address}`, e) - return { assets: [] } + return { assets: [], next: null, previous: null } } } -async function scan (address: Address) { - const inventory: Record = {} +async function loadAssets (address: Address, cursor?: string): Promise { + const set = await fetchAssets(address, cursor) - async function getSet (address: Address, offset = 0) { - const set = await fetchAssets(address, offset) - set.assets.forEach(a => { - inventory[a.id] = a - }) - if (set.assets.length === 50) await getSet(address, offset + 50) - } - - await getSet(address) - return inventory + return (set.next && set.next !== cursor) + ? [...set.assets, ...(await loadAssets(address, set.next))] + : set.assets } export default async function (address: Address) { - let i = await scan(address) - const inventory: Record = {} - let a = Object.keys(i).forEach(a => { - const { collection } = i[a] - if (!inventory[collection.slug]) { - inventory[collection.slug] = { + const assets = await loadAssets(address) + + const inventory = assets.reduce((collectedInventory, asset) => { + const { name, id, token_id, image_url, description, external_link, permalink, traits, asset_contract, collection } = asset + + if (!collectedInventory[collection.slug]) { + collectedInventory[collection.slug] = { meta: { name: collection.name, description: collection.description, @@ -98,8 +110,8 @@ export default async function (address: Address) { assets: {} } } - const { name, id, token_id, image_url, description, external_link, permalink, traits, asset_contract } = i[a] - inventory[collection.slug].assets[id] = { + + collectedInventory[collection.slug].assets[id] = { name, id, tokenId: token_id, @@ -118,9 +130,11 @@ export default async function (address: Address) { description: asset_contract.description, img: asset_contract.image_url, link: asset_contract.external_link - }, - + } } - }) + + return collectedInventory + }, {} as Record) + return inventory } diff --git a/main/index.js b/main/index.js index 89eb3ed82..fc6828454 100644 --- a/main/index.js +++ b/main/index.js @@ -87,7 +87,8 @@ const externalWhitelist = [ 'https://discord.gg/UH7NGqY', 'https://frame.canny.io', 'https://feedback.frame.sh', - 'https://wiki.trezor.io/Trezor_Bridge' + 'https://wiki.trezor.io/Trezor_Bridge', + 'https://opensea.io' ] global.eval = () => { throw new Error(`This app does not support global.eval()`) } // eslint-disable-line @@ -137,7 +138,8 @@ ipcMain.on('dash:reloadSigner', (e, id) => { }) ipcMain.on('tray:openExternal', (e, url) => { - if (externalWhitelist.indexOf(url) > -1) shell.openExternal(url) + const validHost = externalWhitelist.some(entry => url.startsWith(entry)) + if (validHost) shell.openExternal(url) }) ipcMain.on('tray:openExplorer', (e, hash, chain) => {