🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Sign inDemoInstall
Socket

embeddable-nfts

Package Overview
Dependencies
Maintainers
7
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

embeddable-nfts - npm Package Compare versions

Comparing version

to
0.5.1

assets/embedable-nfts.png

47

package.json
{
"name": "embeddable-nfts",
"version": "0.4.8",
"description": "Resuable, embeddable webcomponent for OpenSea assets.",
"version": "0.5.1",
"description": "Reusable, embeddable webcomponent for OpenSea assets.",
"scripts": {

@@ -24,6 +24,6 @@ "test": "echo \"Error: no test specified\" && exit 1",

"dependencies": {
"lit-element": "^2.2.1",
"lit-html": "^1.1.2",
"lit-element": "^3.0.2",
"lit-html": "^2.0.2",
"opensea-js": "^1.1.0",
"web3": "0.20.6"
"web3": "^1.6.1"
},

@@ -36,17 +36,17 @@ "husky": {

"devDependencies": {
"@babel/cli": "^7.8.4",
"@babel/core": "^7.8.7",
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-proposal-decorators": "^7.8.3",
"@babel/preset-env": "^7.8.7",
"@babel/preset-typescript": "^7.8.3",
"@types/node": "^13.9.1",
"@typescript-eslint/eslint-plugin": "^2.23.0",
"@typescript-eslint/parser": "^2.23.0",
"@webcomponents/webcomponentsjs": "^2.4.2",
"@babel/cli": "^7.16.0",
"@babel/core": "^7.16.0",
"@babel/plugin-proposal-class-properties": "^7.16.0",
"@babel/plugin-proposal-decorators": "^7.16.4",
"@babel/preset-env": "^7.16.4",
"@babel/preset-typescript": "^7.16.0",
"@types/node": "^16.11.11",
"@typescript-eslint/eslint-plugin": "^5.5.0",
"@typescript-eslint/parser": "^5.5.0",
"@webcomponents/webcomponentsjs": "^2.6.0",
"html-webpack-plugin": "^3.2.0",
"husky": "^4.2.3",
"prettier": "1.19.1",
"style-loader": "^1.1.3",
"ts-loader": "^6.2.1",
"husky": "^7.0.4",
"prettier": "^2.5.0",
"style-loader": "^3.3.1",
"ts-loader": "^8.2.0",
"tslint": "^6.1.0",

@@ -56,8 +56,9 @@ "tslint-config-prettier": "^1.18.0",

"tslint-plugin-prettier": "^2.3.0",
"typescript": "^3.8.3",
"typescript": "^4.5.2",
"web3-core": "^1.6.1",
"web3-typescript-typings": "^0.10.2",
"webpack": "^4.42.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3"
"webpack": "^4.46.0",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.3"
}
}

@@ -0,2 +1,7 @@

<img style="border-radius: 8px" src="assets/embedable-nfts.png" />
<br /><br />
# Embeddable NFTs
Easily embed OpenSea listings in your website!

@@ -6,7 +11,11 @@

`tokenAddress`\*- The token's contract address.
`tokenId`\* - The token Id of the asset.
`horizontal` - If this is present, the card will be rendered horizontally.
`orientationMode` - If `auto` the card will switch to vertical
mode on mobile (breakpoint is at 600px). In `manual` mode the card will be unaffected.
`orientationMode` - If `auto` the card will switch to vertical
`width` - The width of the embeddable. Ex. values `100%` `250px`. Default: `388px`

@@ -16,8 +25,6 @@

`tokenAddress`\*- The token's contract address.
`network` - The name of the network the asset is on `mainnet` or `testnet`. Default: `mainnet`.
`tokenId`\* - The token Id of the asset.
`referrerAddress` - The address of the referrer. Check out the [SDK docs](https://github.com/ProjectOpenSea/opensea-js#affiliate-program) to learn more about the Affiliate program.
`network` - The name of the network the asset is on `mainnet` or `rinkeby`. Default: `mainnet`.
\*Required inputs

@@ -28,2 +35,3 @@

Add this to your `<head>` tag:
```

@@ -34,2 +42,3 @@ <script src="https://unpkg.com/embeddable-nfts/dist/nft-card.min.js"></script>

Then add this into your code:
```

@@ -40,2 +49,3 @@ <nft-card

network="mainnet"
referrerAddress="YOUR_ADDRESS_HERE"
>

@@ -46,11 +56,14 @@ </nft-card>

### Development
For developers looking to contribute or modify the code, or view the example use the following commands:
```bash
git clone https://github.com/ProjectOpenSea/embeddable_nfts.git
cd embeddable_nfts
npm install
npm run dev:demo
yarn install
yarn run dev:demo
```
#### Development server
This project uses webpack for building and running a development server. Once the server starts, any changes made will trigger a rebuild after which those changes should be reflected in your browser.

@@ -17,3 +17,3 @@ import { css, customElement, html, LitElement, property } from 'lit-element'

height: RANK_HEIGHT + 'px',
marginBottom: RANK_MARGIN + 'px'
marginBottom: RANK_MARGIN + 'px',
}

@@ -25,3 +25,3 @@

height: PROP_HEIGHT + 'px',
marginBottom: PROP_MARGIN + 'px'
marginBottom: PROP_MARGIN + 'px',
}

@@ -33,3 +33,3 @@

const boostStyle = {
height: BOOST_HEIGHT + 'px'
height: BOOST_HEIGHT + 'px',
}

@@ -41,3 +41,3 @@

height: RANK_HEIGHT + 'px',
marginBottom: RANK_MARGIN + 'px'
marginBottom: RANK_MARGIN + 'px',
}

@@ -49,3 +49,3 @@

ranking: RANK_HEIGHT + RANK_MARGIN,
stat: STAT_HEIGHT + STAT_MARGIN
stat: STAT_HEIGHT + STAT_MARGIN,
}

@@ -57,2 +57,3 @@

@property({ type: Object }) public openseaLink?: string
@property({ type: Boolean }) public flippedCard: boolean = false
@property({ type: Boolean }) public loading = true

@@ -72,4 +73,11 @@ @property({ type: Boolean }) public horizontal!: boolean

}
.card-back.is-flipped {
transition-delay: 0.2s;
transition-property: visibility;
visibility: initial;
backface-visibility: initial;
}
.card-back {
position: absolute;
visibility: hidden;
backface-visibility: hidden;

@@ -293,3 +301,3 @@ width: 100%;

numRender,
numRemaining
numRemaining,
}

@@ -332,5 +340,3 @@ }

</div>
<div class="trait_boost-name">
${formatTraitType(trait_type)}
</div>
<div class="trait_boost-name">${formatTraitType(trait_type)}</div>
</div>

@@ -371,9 +377,7 @@ `

${stats.slice(0, numRender).map(
stat =>
(stat) =>
html`
<div class="stat" style=${styleMap(statStyle)}>
<div class="stat-value">${stat.value}</div>
<div class="stat-name">
${formatTraitType(stat.trait_type)}
</div>
<div class="stat-name">${formatTraitType(stat.trait_type)}</div>
</div>

@@ -478,3 +482,3 @@ `

return html`
<div class="card-back">
<div class="card-back ${classMap({ 'is-vertical': !this.horizontal, 'is-flipped': this.flippedCard })}">
<info-button

@@ -490,3 +494,3 @@ style="position: absolute; top: 5px; right: 5px"

class="card-back-inner ${classMap({
'is-vertical': !this.horizontal
'is-vertical': !this.horizontal,
})}"

@@ -530,3 +534,3 @@ >

rankings: [],
boosts: []
boosts: [],
}

@@ -543,5 +547,5 @@ const { traits: assetTraits, collectionTraits } = traitData

...(type === TraitType.Ranking
? { max: (collectionTraits[name].max as unknown) as number }
? { max: collectionTraits[name].max as unknown as number }
: {}),
trait_type: trait.trait_type
trait_type: trait.trait_type,
})

@@ -548,0 +552,0 @@ }

@@ -10,3 +10,3 @@ import { css, customElement, html, LitElement, property } from 'lit-element'

OpenSeaCollection,
OpenSeaFungibleToken
OpenSeaFungibleToken,
} from 'opensea-js/lib/types'

@@ -16,4 +16,3 @@ /* lit-element classes */

import { toBaseDenomination } from './utils'
import { ButtonType, PriceType, State } from './types'
import { BTN_TEXT } from './constants'
import { PriceType, State } from './types'

@@ -23,9 +22,11 @@ @customElement('nft-card-front')

@property({ type: Object }) public asset?: OpenSeaAsset
@property({ type: Boolean }) public isOwnedByAccount!: boolean
@property({ type: String }) public account!: string
@property({ type: Boolean }) public horizontal!: boolean
@property({ type: Object }) public state!: State
@property({ type: Boolean }) public flippedCard: boolean = false
static get styles() {
return css`
.card-front.is-flipped {
display: none;
}
.card-front {

@@ -97,5 +98,3 @@ position: absolute;

.asset-detail-price {
text-align: right;
}
.asset-detail-price {
align-items: flex-end;
font-size: 18px;

@@ -106,9 +105,20 @@ font-weight: 400;

justify-content: flex-end;
align-items: baseline;
line-height: 15px;
text-align: right;
padding: 6px 0;
}
.asset-detail-price img {
margin-left: 5px;
margin: 0 4px;
}
.asset-detail-price-current img {
width: 15px;
align-self: center;
}
.asset-detail-price-previous {
font-size: 14px;
color: rgb(130, 130, 130);
line-height: 10px;
}
.asset-detail-price-previous img {
width: 1ex;
}
.asset-detail-price .value {

@@ -154,3 +164,3 @@ margin-left: 5px;

padding: cardDisplayStyle === 'padded' ? '10px' : '',
'background-size': `${cardDisplayStyle}`
'background-size': `${cardDisplayStyle}`,
}

@@ -182,7 +192,5 @@ }

return html`
<div class="asset-detail-price">
<a class="asset-link" href="${this.asset?.openseaLink}" target="_blank">
${currentPriceTemplate} ${prevPriceTemplate}
</a>
</div>
<a class="asset-link" href="${this.asset?.openseaLink}" target="_blank">
${currentPriceTemplate} ${prevPriceTemplate}
</a>
`

@@ -199,7 +207,7 @@ }

const { openseaLink, collection, assetContract, name } = this.asset
const { openseaLink, collection, name } = this.asset
const { network } = this.state
return html`
<div class="card-front ${classMap({ 'is-vertical': !this.horizontal })}">
<div class="card-front ${classMap({ 'is-vertical': !this.horizontal, 'is-flipped': this.flippedCard })}">
${this.asset.traits.length > 0

@@ -221,3 +229,3 @@ ? html`

href="http://${network === Network.Rinkeby
? 'rinkeby.'
? 'testnets.'
: ''}opensea.io/assets/${collection.slug}"

@@ -227,4 +235,4 @@ target="_blank"

<pill-element
.imageUrl=${assetContract.imageUrl}
.label=${assetContract.name}
.imageUrl=${collection.imageUrl}
.label=${collection.name}
textColor="#828282"

@@ -251,5 +259,3 @@ border="1px solid #E2E6EF"

${this.getAssetPriceTemplate()}
<div class="asset-action-buy">
${this.getButtonTemplate()}
</div>
<div class="asset-action-buy">${this.getButtonTemplate()}</div>
</div>

@@ -267,4 +273,4 @@ </div>

detail: {
type
}
type,
},
})

@@ -280,7 +286,5 @@ this.dispatchEvent(buttonEvent)

return html`
<div class="asset-detail-price">
<div class="asset-detail-price asset-detail-price-${priceType}">
${priceType === PriceType.Previous
? html`
<div class="previous-value">Prev.&nbsp;</div>
`
? html` <div class="previous-value">Prev.&nbsp;</div> `
: null}

@@ -294,3 +298,3 @@ ${paymentToken.imageUrl

`}
<div class="asset-detail-price value ${priceType}-value">
<div class="asset-detail-price-value">
${toBaseDenomination(price, paymentToken.decimals)}

@@ -315,3 +319,3 @@ </div>

'background-image': `url(${imageUrl})`,
...NftCardFrontTemplate.getAssetImageStyles(collection)
...NftCardFrontTemplate.getAssetImageStyles(collection),
})}

@@ -327,3 +331,3 @@ ></div>

<button @click="${(e: any) => this.eventHandler(e, 'view')}">
${BTN_TEXT[ButtonType.Buy]}
buy this item ❯
</button>

@@ -333,51 +337,2 @@ `

// @ts-ignore
private _getButtonTemplate() {
let btnType: ButtonType
if (this.state.hasWeb3) {
if (this.state.isUnlocked) {
if (this.state.isMatchingNetwork) {
if (this.state.isOwnedByAccount) {
// The account owns asset
btnType = ButtonType.Manage
} else {
// Asset is for sale and not owned by currently selected account
btnType = ButtonType.Buy
}
} else {
// Network does not match or connected to unsupported network
btnType = ButtonType.SwitchNetwork // "switchNetwork" + this.state.network
}
} else {
// Wallet is locked or access not granted
btnType = ButtonType.Unlock
}
} else {
// No injected web3 found
btnType = ButtonType.View
}
// If we are informing the user to switch networks we need to append the
// network on which the asset resides
const btnText: string =
btnType === ButtonType.SwitchNetwork
? BTN_TEXT[btnType] + this.state.network
: BTN_TEXT[btnType]
const btnStyle =
btnType === ButtonType.SwitchNetwork
? {
'background-color': 'rgb(183, 183, 183)',
cursor: 'not-allowed'
}
: null
return html`
<button
style=${btnStyle ? styleMap(btnStyle) : ''}
@click="${(e: any) => this.eventHandler(e, btnType)}"
>
${btnText}
</button>
`
}
}
import { css, customElement, html, LitElement, property } from 'lit-element'
import { styleMap } from 'lit-html/directives/style-map'
// @ts-ignore ts error TS7016
import Web3 from 'web3'
import { provider as Web3Provider } from 'web3-core'

@@ -9,3 +8,2 @@ import { Network, OpenSeaPort } from 'opensea-js'

import { NO_WEB3_ERROR } from './constants'
/* lit-element classes */

@@ -16,7 +14,5 @@ import './pill.ts'

import './nft-card-back.ts'
import { ButtonEvent, CustomWindow } from './types'
import { getProvider, networkFromId, networkFromString } from './utils'
import { ButtonEvent } from './types'
import { getProvider, networkFromString } from './utils'
declare const window: CustomWindow
const HORIZONTAL_MIN_CARD_HEIGHT = '200px'

@@ -36,3 +32,3 @@ const VERT_MIN_CARD_HEIGHT = '670px'

Auto = 'auto',
Manual = 'manual'
Manual = 'manual',
}

@@ -44,3 +40,3 @@

* Nft-card element that manages front & back of card.
* Facilitates aquisition and distribution data between
* Facilitates acquisition and distribution data between
* components.

@@ -63,8 +59,8 @@ * Registers <nft-card> as an HTML tag.

@property({ type: String }) public network: Network = Network.Main
@property({ type: String }) public referrerAddress: string = ''
@property({ type: Object }) private asset!: OpenSeaAsset
@property({ type: Object }) private traitData: object = {}
@property({ type: String }) private account: string = ''
@property({ type: String }) private flippedCard: boolean = false
@property({ type: Object }) private provider: Web3.Provider
@property({ type: String }) public flippedCard: boolean = false
@property({ type: Object }) private provider: Web3Provider = null
@property({ type: Object }) private seaport!: OpenSeaPort

@@ -75,6 +71,2 @@

@property({ type: Boolean }) private error = false
@property({ type: Boolean }) private isOwnedByAccount = false
@property({ type: Boolean }) private isUnlocked: boolean = true
@property({ type: Boolean }) private hasWeb3: boolean = false
@property({ type: Boolean }) private isMatchingNetwork: boolean = false

@@ -175,7 +167,3 @@ static get styles() {

this.hasWeb3 = !!window.web3
// Get the web3 provider
this.provider = getProvider()
const networkName = networkFromString(this.network)

@@ -187,3 +175,3 @@ this.seaport = new OpenSeaPort(this.provider, { networkName })

tokenAddress: this.tokenAddress,
tokenId: this.tokenId
tokenId: this.tokenId,
})

@@ -193,3 +181,3 @@

traits: this.asset.traits,
collectionTraits: this.asset.collection.traitStats
collectionTraits: this.asset.collection.traitStats,
}

@@ -204,30 +192,7 @@ } catch (e) {

this.isMatchingNetwork =
networkFromId(this.provider.networkVersion) === this.network
// Tell the component to update with new state
await this.requestUpdate()
// Watch for the account to change then update state of component
this.provider.on('accountsChanged', (accounts: string[]) => {
this.account = accounts.length > 0 ? accounts[0] : ''
this.isOwnedByAccount =
this.asset.owner.address.toLowerCase() === this.account.toLowerCase()
})
this.provider.on('networkChanged', (networkId: string) => {
const network = networkFromId(networkId)
this.isMatchingNetwork = network === this.network
})
}
public async buyAsset() {
if (this.isUnlocked && this.asset.sellOrders) {
const order = this.asset.sellOrders[0]
await this.seaport.fulfillOrder({
order,
accountAddress: this.account
})
}
}
public renderErrorTemplate() {

@@ -243,5 +208,3 @@ return html`

public renderLoaderTemplate() {
return html`
<loader-element></loader-element>
`
return html` <loader-element></loader-element> `
}

@@ -256,9 +219,5 @@

.state=${{
isOwnedByAccount: this.isOwnedByAccount,
isMatchingNetwork: this.isMatchingNetwork,
isUnlocked: this.isUnlocked,
hasWeb3: this.hasWeb3,
network: this.network
network: this.network,
}}
.account=${this.account}
.flippedCard="${this.flippedCard}"
></nft-card-front>

@@ -270,2 +229,3 @@ <nft-card-back

@flip-event="${this.eventHandler}"
.flippedCard="${this.flippedCard}"
></nft-card-back>

@@ -286,3 +246,3 @@ `

minHeight: this.minHeight,
maxWidth: this.maxWidth
maxWidth: this.maxWidth,
})}

@@ -310,11 +270,4 @@ >

case 'view':
case 'manage':
this.goToOpenSea()
break
case 'unlock':
await this.connectWallet()
break
case 'buy':
await this.buyAsset()
break
case 'flip':

@@ -327,34 +280,7 @@ this.flipCard()

private goToOpenSea() {
window.open(this.asset.openseaLink, '_blank')
const url = this.referrerAddress
? `${this.asset.openseaLink}?ref=${this.referrerAddress}`
: this.asset.openseaLink
window.open(url, '_blank')
}
/**
* async connectWallet - Initializes connection to the injected web3 account
* Pre-Conditions: this.provider has been defined - this method should only
* be called if web3 is available. If web3 is available then this.provider
* must be defined
*/
private async connectWallet() {
if (window.web3) {
// If it is modern dapp then show prompt requesting access
if (window.ethereum) {
const ACCESS_DENIED = 4001
await window.ethereum.enable().catch((error: { code: number }) => {
if (error.code === ACCESS_DENIED) {
this.isUnlocked = false
}
})
}
if (this.provider.selectedAddress) {
this.account = this.provider.selectedAddress
this.isOwnedByAccount =
this.asset.owner.address.toLowerCase() === this.account.toLowerCase()
}
} else {
this.isUnlocked = false
alert(NO_WEB3_ERROR)
throw new Error(NO_WEB3_ERROR)
}
}
}

@@ -18,3 +18,3 @@ import { LitElement, html, customElement, property, css } from 'lit-element'

color: this.textColor,
border: this.border
border: this.border,
}

@@ -75,10 +75,6 @@

color: this.textColor,
border: this.border
border: this.border,
})}
>
${this.imageUrl
? html`
<img src="${this.imageUrl}" alt="" />
`
: ''}
${this.imageUrl ? html` <img src="${this.imageUrl}" alt="" /> ` : ''}
<p>${this.label}</p>

@@ -85,0 +81,0 @@ </div>

@@ -10,3 +10,3 @@ import { Network, OpenSeaTraitStats } from 'opensea-js/lib/types'

Ranking = 'ranking',
Boost = 'boost'
Boost = 'boost',
}

@@ -38,28 +38,11 @@

export enum ButtonType {
Manage = 'manage',
Buy = 'buy',
View = 'view',
SwitchNetwork = 'switchNetwork',
Unlock = 'unlock'
}
export enum PriceType {
Current = 'current',
Previous = 'previous'
Previous = 'previous',
}
export interface State {
isOwnedByAccount: boolean
isMatchingNetwork: boolean
isUnlocked: boolean
hasWeb3: boolean
network: Network
}
export interface CustomWindow extends Window {
ethereum: Web3.Provider
web3: Web3
}
export interface ButtonEvent {

@@ -66,0 +49,0 @@ detail: {

@@ -1,2 +0,2 @@

import { CollectionTraits, Trait, TraitType, CustomWindow } from './types'
import { CollectionTraits, Trait, TraitType } from './types'
// @ts-ignore ts error TS7016

@@ -6,4 +6,2 @@ import Web3 from 'web3'

declare const window: CustomWindow
export const formatTraitType = (traitType: string) =>

@@ -67,24 +65,9 @@ traitType.replace(/_/g, ' ')

export const getProvider = () =>
window.ethereum
? window.ethereum
: window.web3
? window.web3.currentProvider
: new Web3.providers.HttpProvider('https://mainnet.infura.io')
(Web3.givenProvider || new Web3.providers.HttpProvider('https://mainnet.infura.io'))
// Given the network version this method returns the network name
// Since only Main & Rinkeby are supported we ignore the other networks
export const networkFromId = (id: string) => {
switch (id) {
case '1':
return Network.Main
case '4':
return Network.Rinkeby
default:
return null
}
}
export const networkFromString = (name: string) => {
switch (name) {
case 'rinkeby':
case 'testnet':
case 'testnets':
return Network.Rinkeby

@@ -91,0 +74,0 @@ case 'mainnet':

@@ -30,3 +30,3 @@ {

"member-access": true,
"member-ordering": [true, "public-before-private", "static-before-instance", "variables-before-functions"],
"member-ordering": [true, {"order": "fields-first"}],
"newline-before-return": false,

@@ -33,0 +33,0 @@ "new-parens": true,

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet