整理上链流程
This commit is contained in:
parent
f26f278cec
commit
1ec2178fc9
6
components.d.ts
vendored
6
components.d.ts
vendored
@ -30,9 +30,10 @@ declare module 'vue' {
|
||||
Card: typeof import('./src/components/common/card.vue')['default']
|
||||
Cart: typeof import('./src/components/cart/index.vue')['default']
|
||||
ChainModel: typeof import('./src/components/home/ChainModel.vue')['default']
|
||||
ChainSelectModel: typeof import('./src/components/chain/ChainSelectModel.vue')['default']
|
||||
ChipCard: typeof import('./src/components/home/ChipCard.vue')['default']
|
||||
Collectibles: typeof import('./src/components/assets/collectibles.vue')['default']
|
||||
copy: typeof import('./src/components/common/searchView/rank copy.vue')['default']
|
||||
copy: typeof import('./src/components/wallet/WalletModel copy.vue')['default']
|
||||
GameFeatures: typeof import('./src/components/home/GameFeatures.vue')['default']
|
||||
GameVideo: typeof import('./src/components/home/GameVideo.vue')['default']
|
||||
Gold: typeof import('./src/components/common/searchView/gold.vue')['default']
|
||||
@ -56,7 +57,6 @@ declare module 'vue' {
|
||||
Please: typeof import('./src/components/global/Please.vue')['default']
|
||||
Price: typeof import('./src/components/common/searchView/Price.vue')['default']
|
||||
Rank: typeof import('./src/components/common/searchView/rank.vue')['default']
|
||||
'Rank copy': typeof import('./src/components/common/searchView/rank copy.vue')['default']
|
||||
Roadmap: typeof import('./src/components/about/Roadmap.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
@ -68,6 +68,8 @@ declare module 'vue' {
|
||||
TeamVision: typeof import('./src/components/about/TeamVision.vue')['default']
|
||||
Trading: typeof import('./src/components/assets/trading.vue')['default']
|
||||
TradingCard: typeof import('./src/components/common/tradingCard.vue')['default']
|
||||
WalletModel: typeof import('./src/components/wallet/WalletModel.vue')['default']
|
||||
WalletSelectModel: typeof import('./src/components/chain/WalletSelectModel.vue')['default']
|
||||
WeaponCard: typeof import('./src/components/home/WeaponCard.vue')['default']
|
||||
WeaponModelLoader: typeof import('./src/components/home/WeaponModelLoader.vue')['default']
|
||||
WhatCounterFire: typeof import('./src/components/home/WhatCounterFire.vue')['default']
|
||||
|
20
src/components/chain/BlockChain.js
Normal file
20
src/components/chain/BlockChain.js
Normal file
@ -0,0 +1,20 @@
|
||||
import {PassportWallet} from '@/components/chain/PassportWallet';
|
||||
import { createSingleton } from '@/utils/singleton';
|
||||
|
||||
const LOCAL_WALLET_KEY = 'wallet_type';
|
||||
|
||||
class CBlockChain {
|
||||
constructor() {
|
||||
|
||||
};
|
||||
|
||||
initWallet() {
|
||||
console.log('init wallet')
|
||||
};
|
||||
|
||||
preparePassport() {
|
||||
new PassportWallet()
|
||||
};
|
||||
}
|
||||
|
||||
export const BlockChain = createSingleton(CBlockChain);
|
151
src/components/chain/ChainSelectModel.vue
Normal file
151
src/components/chain/ChainSelectModel.vue
Normal file
@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<div class="chain-modal" v-if="props.visible" :class="{ mobile: 'mobile' }">
|
||||
<div class="modal-bg" @click="cancelSelect"></div>
|
||||
<div class="modal-content" :class="{ mobile: 'mobile' }">
|
||||
<div class="modal-title">You need to connect to supported network</div>
|
||||
<div
|
||||
class="chain-modal-card"
|
||||
v-for="data in currentDatas"
|
||||
:key="data.name"
|
||||
@click="cardClicked(data.id)"
|
||||
>
|
||||
<div class="icon">
|
||||
<img :src="data.logo" :alt="data.name" />
|
||||
</div>
|
||||
<div class="name">{{ data.name }}</div>
|
||||
<div class="desc">{{ data.desc }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import { useChainStore } from "@/store/chain";
|
||||
|
||||
const chain = useChainStore();
|
||||
const props = defineProps({
|
||||
visible: Boolean,
|
||||
close: Function,
|
||||
});
|
||||
const chainDatas = computed(() => {
|
||||
return [...chain.chainManager.availableChains.values()];
|
||||
});
|
||||
|
||||
const currentDatas = computed(() => {
|
||||
return chainDatas.value;
|
||||
});
|
||||
|
||||
function cardClicked(id) {
|
||||
hideModal(id);
|
||||
}
|
||||
|
||||
function cancelSelect() {
|
||||
hideModal({errcode: 1, errmsg: "user cancel select chain"});
|
||||
}
|
||||
|
||||
function hideModal(result = null) {
|
||||
props.close(result);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.chain-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow: auto;
|
||||
margin: 0;
|
||||
z-index: 10;
|
||||
.modal-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow: auto;
|
||||
margin: 0;
|
||||
background-color: #000000a3;
|
||||
}
|
||||
.modal-content {
|
||||
width: 500px;
|
||||
max-height: 400px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.mobile {
|
||||
width: 100vw;
|
||||
}
|
||||
.modal-title {
|
||||
background-color: rgb(255, 255, 255);
|
||||
color: black;
|
||||
border-radius: 12px 12px 0 0;
|
||||
padding: 15px 20px;
|
||||
border-bottom: 1px solid rgba(195, 195, 195, 0.14);
|
||||
}
|
||||
.chain-modal-card {
|
||||
background-color: rgb(255, 255, 255);
|
||||
transition: background-color 0.2s ease-in-out 0s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
-webkit-box-pack: center;
|
||||
justify-content: center;
|
||||
-webkit-box-align: center;
|
||||
align-items: center;
|
||||
padding: 24px 16px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
&:first-child {
|
||||
border-radius: 12px 12px 0 0;
|
||||
}
|
||||
&:not(:first-child) {
|
||||
border-top: 1px solid rgba(195, 195, 195, 0.14);
|
||||
}
|
||||
&:last-child {
|
||||
border-radius: 0 0 12px 12px;
|
||||
}
|
||||
.icon {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
display: flex;
|
||||
border-radius: 50%;
|
||||
overflow: visible;
|
||||
box-shadow: none;
|
||||
-webkit-box-pack: center;
|
||||
justify-content: center;
|
||||
-webkit-box-align: center;
|
||||
align-items: center;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.icon-svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
fill: currentColor;
|
||||
color: unset;
|
||||
stroke: none;
|
||||
}
|
||||
}
|
||||
.name {
|
||||
width: 100%;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
margin-top: 0.5em;
|
||||
color: rgb(12, 12, 13);
|
||||
}
|
||||
.desc {
|
||||
width: 100%;
|
||||
font-size: 18px;
|
||||
margin: 0.333em 0px;
|
||||
color: rgb(169, 169, 188);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
222
src/components/chain/Market.js
Normal file
222
src/components/chain/Market.js
Normal file
@ -0,0 +1,222 @@
|
||||
import { baseConfig } from './PassportWallet';
|
||||
import { orderbook } from '@imtbl/sdk';
|
||||
const marketAddress = import.meta.env.VUE_APP_PASSPORT_MARKET_ADDRESS
|
||||
|
||||
const NATIVE = 'NATIVE'
|
||||
const ERC20 = 'ERC20'
|
||||
|
||||
class ImtblMarket {
|
||||
constructor() {
|
||||
this.client = new orderbook.Orderbook({ baseConfig });
|
||||
}
|
||||
|
||||
updateProvider(provider) {
|
||||
this.provider = provider;
|
||||
this.signer = this.provider.getSigner();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询某个nft的所有挂单
|
||||
* @param {*} contractAddress
|
||||
* @returns
|
||||
*/
|
||||
async listListings(contractAddress){
|
||||
const listOfListings = await this.client.listListings({
|
||||
sellItemContractAddress: contractAddress,
|
||||
status: orderbook.OrderStatusName.ACTIVE,
|
||||
pageSize: 50,
|
||||
});
|
||||
return listOfListings;
|
||||
};
|
||||
|
||||
/**
|
||||
* 准备一个ERC721的挂单
|
||||
* @returns
|
||||
*/
|
||||
async _prepareERC721Listing({ contractAddress, tokenId, type = 'ERC721', currencyAddress, currencyAmount}){
|
||||
const offerer = await this.signer.getAddress();
|
||||
const buyData = {
|
||||
amount: currencyAmount,
|
||||
}
|
||||
if (currencyAddress == NATIVE) {
|
||||
buyData.type = NATIVE
|
||||
} else {
|
||||
buyData.type = ERC20
|
||||
buyData.contractAddress = currencyAddress
|
||||
}
|
||||
const preparedListing = await this.client.prepareListing({
|
||||
makerAddress: offerer,
|
||||
buy: buyData,
|
||||
sell: {
|
||||
contractAddress,
|
||||
tokenId,
|
||||
type,
|
||||
},
|
||||
});
|
||||
|
||||
let orderSignature = ''
|
||||
for (const action of preparedListing.actions) {
|
||||
// If the user hasn't yet approved the Immutable Seaport contract to transfer assets from this
|
||||
// collection on their behalf they'll need to do so before they create an order
|
||||
if (action.type === orderbook.ActionType.TRANSACTION) {
|
||||
const builtTx = await action.buildTransaction()
|
||||
console.log(`Submitting ${action.purpose} transaction`)
|
||||
await signer.sendTransaction(builtTx);
|
||||
}
|
||||
|
||||
// For an order to be created (and subsequently filled), Immutable needs a valid signature for the order data.
|
||||
// This signature is stored off-chain and is later provided to any user wishing to fulfil the open order.
|
||||
// The signature only allows the order to be fulfilled if it meets the conditions specified by the user that created the listing.
|
||||
if (action.type === orderbook.ActionType.SIGNABLE) {
|
||||
orderSignature = await signer._signTypedData(
|
||||
action.message.domain,
|
||||
action.message.types,
|
||||
action.message.value,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return { preparedListing, orderSignature }
|
||||
}
|
||||
/**
|
||||
* 创建一个挂单
|
||||
* @param {*} preparedListing
|
||||
* @param {*} orderSignature
|
||||
*/
|
||||
async _createListing(
|
||||
preparedListing,
|
||||
orderSignature,
|
||||
currencyAmount
|
||||
){
|
||||
const amount = (BigInt(currencyAmount) * 2n / 100n).toString()
|
||||
const order = await this.client.createListing({
|
||||
orderComponents: preparedListing.orderComponents,
|
||||
orderHash: preparedListing.orderHash,
|
||||
orderSignature,
|
||||
// Optional maker marketplace fee
|
||||
makerFees: [{
|
||||
amount,
|
||||
recipientAddress: marketAddress, // Replace address with your own marketplace address
|
||||
}],
|
||||
});
|
||||
console.log('order:', order);
|
||||
return order
|
||||
};
|
||||
|
||||
/**
|
||||
* 出售一个ERC721的NFT
|
||||
* doc: https://docs.immutable.com/docs/zkEVM/products/orderbook/create-listing
|
||||
* @param {string} contractAddress NFT的合约地址
|
||||
* @param {string} tokenId NFT的tokenId
|
||||
* @param {string} currencyAddress NATIVE 或者 ERC20的合约地址
|
||||
* @param {string} currencyAmount 出售价格, 单位 wei
|
||||
*/
|
||||
async beginSellERC721({contractAddress, tokenId, currencyAddress, currencyAmount}) {
|
||||
const { preparedListing, orderSignature } =
|
||||
await this._prepareERC721Listing({contractAddress, tokenId, currencyAddress, currencyAmount});
|
||||
const order = await this._createListing(preparedListing, orderSignature, currencyAmount);
|
||||
return order
|
||||
}
|
||||
/**
|
||||
* 开始购买
|
||||
* doc: https://docs.immutable.com/docs/zkEVM/products/orderbook/fill
|
||||
* @param {*} listingId
|
||||
*/
|
||||
async beginBuy(listingId) {
|
||||
const fulfiller = await this.signer.getAddress();
|
||||
// const fulfiller = marketAddress
|
||||
console.log(listingId,fulfiller)
|
||||
const { actions, expiration, order } = await this.client.fulfillOrder(
|
||||
listingId,
|
||||
fulfiller,
|
||||
[]
|
||||
);
|
||||
console.log(`Fulfilling listing ${order}, transaction expiry ${expiration}`);
|
||||
for (const action of actions) {
|
||||
if (action.type === orderbook.ActionType.TRANSACTION) {
|
||||
const builtTx = await action.buildTransaction();
|
||||
console.log(`Submitting ${action.purpose} transaction`);
|
||||
await signer.sendTransaction(builtTx);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 批量购买
|
||||
* doc: https://docs.immutable.com/docs/zkEVM/products/orderbook/fill-bulk
|
||||
* @param { string[] } listingIds: listingId列表
|
||||
*/
|
||||
async batchBuy(listingIds) {
|
||||
const fulfiller = await this.signer.getAddress();
|
||||
// console.log(listingIds, marketAddress,'---')
|
||||
// return
|
||||
try {
|
||||
const fulfillResponse = await this.client.fulfillBulkOrders(
|
||||
listingIds.map((listingId) => ({
|
||||
listingId,
|
||||
// you could have up to 2 marketplace fees
|
||||
takerFees: [],
|
||||
})),
|
||||
fulfiller
|
||||
);
|
||||
|
||||
if (fulfillResponse.sufficientBalance) {
|
||||
const { actions, expiration, fulfillableOrders, unfulfillableOrders } = fulfillResponse;
|
||||
// depending on the application, we can either throw an error if some orders are not fulfillable
|
||||
// or we can ignore these unfulfillable orders and proceed with fulfillment
|
||||
if (unfulfillableOrders.length > 0) {
|
||||
throw new Error(
|
||||
`Not all orders are fulfillable - unfulfillable orders: ${unfulfillableOrders}`
|
||||
);
|
||||
}
|
||||
for (const action of actions) {
|
||||
if (action.type === orderbook.ActionType.TRANSACTION) {
|
||||
const builtTx = await action.buildTransaction();
|
||||
console.log(`Submitting ${action.purpose} transaction`);
|
||||
await signer.sendTransaction(builtTx);
|
||||
}
|
||||
}
|
||||
console.log(
|
||||
`Fulfilling listings ${fulfillableOrders}, transaction expiry ${expiration}`
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Fulfill bulk orders request failed with ${e}`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 取消交易
|
||||
* doc: https://docs.immutable.com/docs/zkEVM/products/orderbook/cancel
|
||||
* @param {*} listingIds
|
||||
* @returns
|
||||
*/
|
||||
async cancelOrder(listingIds) {
|
||||
const account = await this.signer.getAddress();
|
||||
const { signableAction } = await this.client.prepareOrderCancellations(listingIds);
|
||||
const cancellationSignature = await this.signer._signTypedData(
|
||||
signableAction.message.domain,
|
||||
signableAction.message.types,
|
||||
signableAction.message.value,
|
||||
)
|
||||
return this.client.cancelOrders(listingIds, account, cancellationSignature)
|
||||
}
|
||||
/**
|
||||
* 取消交易, onChain
|
||||
* doc: https://docs.immutable.com/docs/zkEVM/products/orderbook/cancel
|
||||
* @param {*} listingIds
|
||||
* @returns
|
||||
*/
|
||||
async cancelOrdersOnChain(listingIds) {
|
||||
const offerer = await this.signer.getAddress();
|
||||
const { cancellationAction } = await this.client.cancelOrdersOnChain(
|
||||
listingIds,
|
||||
offerer
|
||||
);
|
||||
|
||||
const unsignedCancelOrderTransaction = await cancellationAction.buildTransaction();
|
||||
const receipt = await this.signer.sendTransaction(unsignedCancelOrderTransaction);
|
||||
return receipt;
|
||||
}
|
||||
}
|
||||
|
||||
export const Market = createSingleton(ImtblMarket)
|
74
src/components/chain/PassportWallet.js
Normal file
74
src/components/chain/PassportWallet.js
Normal file
@ -0,0 +1,74 @@
|
||||
import { config, passport, orderbook, checkout } from '@imtbl/sdk';
|
||||
import { createSingleton } from '@/utils/singleton';
|
||||
import { providers } from 'ethers';
|
||||
|
||||
const environment = process.env.NODE_ENV === 'production' ? config.Environment.PRODUCTION : config.Environment.SANDBOX;
|
||||
const publishableKey = import.meta.env.VUE_APP_PASSPORT_PUBLISHABLE_KEY
|
||||
const clientId = import.meta.env.VUE_APP_PASSPORT_CLIENT_ID
|
||||
const redirectUri = import.meta.env.VUE_APP_PASSPORT_REDIRECT_URI
|
||||
const logoutRedirectUri = import.meta.env.VUE_APP_PASSPORT_LOGOUT_URI
|
||||
|
||||
|
||||
export const baseConfig = { environment, publishableKey }
|
||||
class LPassportWallet {
|
||||
constructor() {
|
||||
this.passportInstance = new passport.Passport({
|
||||
baseConfig,
|
||||
clientId, // replace with your client ID from Hub
|
||||
redirectUri, // replace with one of your redirect URIs from Hub
|
||||
logoutRedirectUri, // replace with one of your logout URIs from Hub
|
||||
audience: 'platform_api',
|
||||
scope: 'openid offline_access email transact',
|
||||
popupOverlayOptions: {
|
||||
disableGenericPopupOverlay: false, // Set to true to disable the generic pop-up overlay
|
||||
disableBlockedPopupOverlay: false, // Set to true to disable the blocked pop-up overlay
|
||||
}
|
||||
});
|
||||
this.passportInstance.loginCallback().then(()=>{}).catch(err=>{});
|
||||
this.client = new orderbook.Orderbook({ baseConfig });
|
||||
}
|
||||
async initWidget() {
|
||||
const checkoutSDK = new checkout.Checkout({
|
||||
baseConfig,
|
||||
passport: this.passportInstance,
|
||||
bridge: { enable: true },
|
||||
swap: { enable: true },
|
||||
onRamp: { enable: true }
|
||||
});
|
||||
|
||||
const widgets = await checkoutSDK.widgets({
|
||||
config: { theme: checkout.WidgetTheme.DARK },
|
||||
});
|
||||
|
||||
// RECOMMENDED - create all of the widgets once at the start of your application
|
||||
// use the created widgets throughout your application to mount and unmount in specific parts of your application
|
||||
const connect = widgets.create(checkout.WidgetType.CONNECT);
|
||||
const wallet = widgets.create(checkout.WidgetType.WALLET); // you can optionally pass in additional config per widget
|
||||
const swap = widgets.create(checkout.WidgetType.SWAP);
|
||||
const bridge = widgets.create(checkout.WidgetType.BRIDGE);
|
||||
const onramp = widgets.create(checkout.WidgetType.ONRAMP);
|
||||
|
||||
// Mount the wallet widget passing the element id of where to mount the widget
|
||||
connect.mount('wallet');
|
||||
}
|
||||
get nativeProvider() {
|
||||
return this.passportInstance.connectEvm();
|
||||
}
|
||||
|
||||
get web3Provider() {
|
||||
const passportProvider = this.passportInstance.connectEvm();
|
||||
return new providers.Web3Provider(passportProvider);
|
||||
}
|
||||
|
||||
|
||||
async getAccessToken() {
|
||||
return await this.passportInstance.getAccessToken();
|
||||
}
|
||||
|
||||
async logout() {
|
||||
await this.passportInstance.logout();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const PassportWallet = createSingleton(LPassportWallet)
|
160
src/components/chain/WalletSelectModel.vue
Normal file
160
src/components/chain/WalletSelectModel.vue
Normal file
@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<div class="chain-modal" v-if="props.visible" :class="{ mobile: 'mobile' }">
|
||||
<div class="modal-bg" @click="cancelSelect"></div>
|
||||
<div class="modal-content" :class="{ mobile: 'mobile' }">
|
||||
<div class="modal-title">You need to connect to supported network</div>
|
||||
<div
|
||||
class="chain-modal-card"
|
||||
v-for="data in currentDatas"
|
||||
:key="data.name"
|
||||
@click="cardClicked(data.id)"
|
||||
>
|
||||
<div class="icon">
|
||||
<img :src="data.logo" :alt="data.name" />
|
||||
</div>
|
||||
<div class="name">{{ data.name }}</div>
|
||||
<div class="desc">{{ data.desc }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import { ALL_PROVIDERS } from "@/configs/configchain";
|
||||
import { PassportWallet } from '@/components/chain/PassportWallet';
|
||||
import { providers } from "ethers"
|
||||
|
||||
const props = defineProps({
|
||||
visible: Boolean,
|
||||
close: Function,
|
||||
});
|
||||
|
||||
const allProviders = {
|
||||
1: window.ethereum,
|
||||
2: window.okxwallet,
|
||||
3: new PassportWallet().nativeProvider
|
||||
}
|
||||
|
||||
const currentDatas = computed(() => {
|
||||
return ALL_PROVIDERS;
|
||||
});
|
||||
|
||||
async function cardClicked(id) {
|
||||
console.log("card clicked:", id);
|
||||
const provider = allProviders[id];
|
||||
const web3Provider = new providers.Web3Provider(provider);
|
||||
const accounts = await web3Provider.provider.request({ method: "eth_requestAccounts" });
|
||||
console.log(accounts)
|
||||
hideModal({errcode: 0, provider: web3Provider, wallet: id, accounts});
|
||||
}
|
||||
|
||||
function cancelSelect() {
|
||||
hideModal({errcode: 1, errmsg: "user cancel select wallet"});
|
||||
}
|
||||
|
||||
function hideModal(result = null) {
|
||||
props.close(result);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.chain-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow: auto;
|
||||
margin: 0;
|
||||
z-index: 10;
|
||||
.modal-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow: auto;
|
||||
margin: 0;
|
||||
background-color: #000000a3;
|
||||
}
|
||||
.modal-content {
|
||||
width: 500px;
|
||||
max-height: 400px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.mobile {
|
||||
width: 100vw;
|
||||
}
|
||||
.modal-title {
|
||||
background-color: rgb(255, 255, 255);
|
||||
color: black;
|
||||
border-radius: 12px 12px 0 0;
|
||||
padding: 15px 20px;
|
||||
border-bottom: 1px solid rgba(195, 195, 195, 0.14);
|
||||
}
|
||||
.chain-modal-card {
|
||||
background-color: rgb(255, 255, 255);
|
||||
transition: background-color 0.2s ease-in-out 0s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
-webkit-box-pack: center;
|
||||
justify-content: center;
|
||||
-webkit-box-align: center;
|
||||
align-items: center;
|
||||
padding: 24px 16px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
&:first-child {
|
||||
border-radius: 12px 12px 0 0;
|
||||
}
|
||||
&:not(:first-child) {
|
||||
border-top: 1px solid rgba(195, 195, 195, 0.14);
|
||||
}
|
||||
&:last-child {
|
||||
border-radius: 0 0 12px 12px;
|
||||
}
|
||||
.icon {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
display: flex;
|
||||
border-radius: 50%;
|
||||
overflow: visible;
|
||||
box-shadow: none;
|
||||
-webkit-box-pack: center;
|
||||
justify-content: center;
|
||||
-webkit-box-align: center;
|
||||
align-items: center;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.icon-svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
fill: currentColor;
|
||||
color: unset;
|
||||
stroke: none;
|
||||
}
|
||||
}
|
||||
.name {
|
||||
width: 100%;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
margin-top: 0.5em;
|
||||
color: rgb(12, 12, 13);
|
||||
}
|
||||
.desc {
|
||||
width: 100%;
|
||||
font-size: 18px;
|
||||
margin: 0.333em 0px;
|
||||
color: rgb(169, 169, 188);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -71,6 +71,8 @@ import { useCopyToClipboard } from "./../../hooks/useCopyToClipboard";
|
||||
import { PassportWallet } from "@/wallet/passPort"
|
||||
import { useImmutableStore } from "@/store/immutable"
|
||||
import { useMarketplaceStore } from "@/store/marketplace"
|
||||
import WalletSelectModel from "@/components/chain/WalletSelectModel.vue"
|
||||
import { createModal } from "@/utils/model.util"
|
||||
|
||||
import Cart from "@/components/cart/index.vue"
|
||||
|
||||
@ -228,28 +230,32 @@ watchEffect(() => {
|
||||
|
||||
// --------------------------------
|
||||
const immuTableLogin = async () => {
|
||||
try{
|
||||
const walletLogin = await new PassportWallet().connect()
|
||||
immutableStore.accessToken = walletLogin.accessToken
|
||||
immutableStore.accounts = walletLogin.accounts[0]
|
||||
localStorage.setItem('assessToken', walletLogin.accessToken)
|
||||
localStorage.setItem('assessAddress', walletLogin.accounts[0])
|
||||
// console.log(walletLogin)
|
||||
/*
|
||||
accessToken
|
||||
accounts
|
||||
profile:
|
||||
let rewardModal = createModal(WalletSelectModel, {})
|
||||
|
||||
*/
|
||||
// loginShowMenu.value = !loginShowMenu.value;
|
||||
// const list = await new PassportWallet().beginSellERC721({
|
||||
// contractAddress: '',
|
||||
// tokenId: ''
|
||||
// });
|
||||
// console.log(list)
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
let result = await rewardModal.show()
|
||||
console.log(`select result : ${result.errcode}`)
|
||||
// try{
|
||||
// const walletLogin = await new PassportWallet().connect()
|
||||
// immutableStore.accessToken = walletLogin.accessToken
|
||||
// immutableStore.accounts = walletLogin.accounts[0]
|
||||
// localStorage.setItem('assessToken', walletLogin.accessToken)
|
||||
// localStorage.setItem('assessAddress', walletLogin.accounts[0])
|
||||
// // console.log(walletLogin)
|
||||
// /*
|
||||
// accessToken
|
||||
// accounts
|
||||
// profile:
|
||||
|
||||
// */
|
||||
// // loginShowMenu.value = !loginShowMenu.value;
|
||||
// // const list = await new PassportWallet().beginSellERC721({
|
||||
// // contractAddress: '',
|
||||
// // tokenId: ''
|
||||
// // });
|
||||
// // console.log(list)
|
||||
// } catch (e) {
|
||||
// console.log(e);
|
||||
// }
|
||||
}
|
||||
|
||||
const immuTableLogout = async () => {
|
||||
|
@ -9,9 +9,15 @@ export const ALL_PROVIDERS = [
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "WalletConnect",
|
||||
name: "OKX",
|
||||
logo: "data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHdpZHRoPSI1MTIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxyYWRpYWxHcmFkaWVudCBpZD0iYSIgY3g9IjAlIiBjeT0iNTAlIiByPSIxMDAlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiM1ZDlkZjYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMwMDZmZmYiLz48L3JhZGlhbEdyYWRpZW50PjxnIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PHBhdGggZD0ibTI1NiAwYzE0MS4zODQ4OTYgMCAyNTYgMTE0LjYxNTEwNCAyNTYgMjU2cy0xMTQuNjE1MTA0IDI1Ni0yNTYgMjU2LTI1Ni0xMTQuNjE1MTA0LTI1Ni0yNTYgMTE0LjYxNTEwNC0yNTYgMjU2LTI1NnoiIGZpbGw9InVybCgjYSkiLz48cGF0aCBkPSJtNjQuNjkxNzU1OCAzNy43MDg4Mjk4YzUxLjUzMjgwNzItNTAuMjc4NDM5NyAxMzUuMDgzOTk0Mi01MC4yNzg0Mzk3IDE4Ni42MTY3OTkyIDBsNi4yMDIwNTcgNi4wNTEwOTA2YzIuNTc2NjQgMi41MTM5MjE4IDIuNTc2NjQgNi41ODk3OTQ4IDAgOS4xMDM3MTc3bC0yMS4yMTU5OTggMjAuNjk5NTc1OWMtMS4yODgzMjEgMS4yNTY5NjE5LTMuMzc3MSAxLjI1Njk2MTktNC42NjU0MjEgMGwtOC41MzQ3NjYtOC4zMjcwMjA1Yy0zNS45NTA1NzMtMzUuMDc1NDk2Mi05NC4yMzc5NjktMzUuMDc1NDk2Mi0xMzAuMTg4NTQ0IDBsLTkuMTQwMDI4MiA4LjkxNzU1MTljLTEuMjg4MzIxNyAxLjI1Njk2MDktMy4zNzcxMDE2IDEuMjU2OTYwOS00LjY2NTQyMDggMGwtMjEuMjE1OTk3My0yMC42OTk1NzU5Yy0yLjU3NjY0MDMtMi41MTM5MjI5LTIuNTc2NjQwMy02LjU4OTc5NTggMC05LjEwMzcxNzd6bTIzMC40OTM0ODUyIDQyLjgwODkxMTcgMTguODgyMjc5IDE4LjQyMjcyNjJjMi41NzY2MjcgMi41MTM5MTAzIDIuNTc2NjQyIDYuNTg5NzU5My4wMDAwMzIgOS4xMDM2ODYzbC04NS4xNDE0OTggODMuMDcwMzU4Yy0yLjU3NjYyMyAyLjUxMzk0MS02Ljc1NDE4MiAyLjUxMzk2OS05LjMzMDg0LjAwMDA2Ni0uMDAwMDEtLjAwMDAxLS4wMDAwMjMtLjAwMDAyMy0uMDAwMDMzLS4wMDAwMzRsLTYwLjQyODI1Ni01OC45NTc0NTFjLS42NDQxNi0uNjI4NDgxLTEuNjg4NTUtLjYyODQ4MS0yLjMzMjcxIDAtLjAwMDAwNC4wMDAwMDQtLjAwMDAwOC4wMDAwMDctLjAwMDAxMi4wMDAwMTFsLTYwLjQyNjk2ODMgNTguOTU3NDA4Yy0yLjU3NjYxNDEgMi41MTM5NDctNi43NTQxNzQ2IDIuNTEzOTktOS4zMzA4NDA4LjAwMDA5Mi0uMDAwMDE1MS0uMDAwMDE0LS4wMDAwMzA5LS4wMDAwMjktLjAwMDA0NjctLjAwMDA0NmwtODUuMTQzODY3NzQtODMuMDcxNDYzYy0yLjU3NjYzOTI4LTIuNTEzOTIxLTIuNTc2NjM5MjgtNi41ODk3OTUgMC05LjEwMzcxNjNsMTguODgyMzEyNjQtMTguNDIyNjk1NWMyLjU3NjYzOTMtMi41MTM5MjIyIDYuNzU0MTk5My0yLjUxMzkyMjIgOS4zMzA4Mzk3IDBsNjAuNDI5MTM0NyA1OC45NTgyNzU4Yy42NDQxNjA4LjYyODQ4IDEuNjg4NTQ5NS42Mjg0OCAyLjMzMjcxMDMgMCAuMDAwMDA5NS0uMDAwMDA5LjAwMDAxODItLjAwMDAxOC4wMDAwMjc3LS4wMDAwMjVsNjAuNDI2MTA2NS01OC45NTgyNTA4YzIuNTc2NTgxLTIuNTEzOTggNi43NTQxNDItMi41MTQwNzQzIDkuMzMwODQtLjAwMDIxMDMuMDAwMDM3LjAwMDAzNTQuMDAwMDcyLjAwMDA3MDkuMDAwMTA3LjAwMDEwNjNsNjAuNDI5MDU2IDU4Ljk1ODM1NDhjLjY0NDE1OS42Mjg0NzkgMS42ODg1NDkuNjI4NDc5IDIuMzMyNzA5IDBsNjAuNDI4MDc5LTU4Ljk1NzE5MjVjMi41NzY2NC0yLjUxMzkyMzEgNi43NTQxOTktMi41MTM5MjMxIDkuMzMwODM5IDB6IiBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9Im5vbnplcm8iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDk4IDE2MCkiLz48L2c+PC9zdmc+",
|
||||
desc: "Scan with WalletConnect to connect",
|
||||
desc: "Connect to your OKX Wallet",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "Passport",
|
||||
logo: "data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIHdpZHRoPSI1MTIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxyYWRpYWxHcmFkaWVudCBpZD0iYSIgY3g9IjAlIiBjeT0iNTAlIiByPSIxMDAlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiM1ZDlkZjYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMwMDZmZmYiLz48L3JhZGlhbEdyYWRpZW50PjxnIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PHBhdGggZD0ibTI1NiAwYzE0MS4zODQ4OTYgMCAyNTYgMTE0LjYxNTEwNCAyNTYgMjU2cy0xMTQuNjE1MTA0IDI1Ni0yNTYgMjU2LTI1Ni0xMTQuNjE1MTA0LTI1Ni0yNTYgMTE0LjYxNTEwNC0yNTYgMjU2LTI1NnoiIGZpbGw9InVybCgjYSkiLz48cGF0aCBkPSJtNjQuNjkxNzU1OCAzNy43MDg4Mjk4YzUxLjUzMjgwNzItNTAuMjc4NDM5NyAxMzUuMDgzOTk0Mi01MC4yNzg0Mzk3IDE4Ni42MTY3OTkyIDBsNi4yMDIwNTcgNi4wNTEwOTA2YzIuNTc2NjQgMi41MTM5MjE4IDIuNTc2NjQgNi41ODk3OTQ4IDAgOS4xMDM3MTc3bC0yMS4yMTU5OTggMjAuNjk5NTc1OWMtMS4yODgzMjEgMS4yNTY5NjE5LTMuMzc3MSAxLjI1Njk2MTktNC42NjU0MjEgMGwtOC41MzQ3NjYtOC4zMjcwMjA1Yy0zNS45NTA1NzMtMzUuMDc1NDk2Mi05NC4yMzc5NjktMzUuMDc1NDk2Mi0xMzAuMTg4NTQ0IDBsLTkuMTQwMDI4MiA4LjkxNzU1MTljLTEuMjg4MzIxNyAxLjI1Njk2MDktMy4zNzcxMDE2IDEuMjU2OTYwOS00LjY2NTQyMDggMGwtMjEuMjE1OTk3My0yMC42OTk1NzU5Yy0yLjU3NjY0MDMtMi41MTM5MjI5LTIuNTc2NjQwMy02LjU4OTc5NTggMC05LjEwMzcxNzd6bTIzMC40OTM0ODUyIDQyLjgwODkxMTcgMTguODgyMjc5IDE4LjQyMjcyNjJjMi41NzY2MjcgMi41MTM5MTAzIDIuNTc2NjQyIDYuNTg5NzU5My4wMDAwMzIgOS4xMDM2ODYzbC04NS4xNDE0OTggODMuMDcwMzU4Yy0yLjU3NjYyMyAyLjUxMzk0MS02Ljc1NDE4MiAyLjUxMzk2OS05LjMzMDg0LjAwMDA2Ni0uMDAwMDEtLjAwMDAxLS4wMDAwMjMtLjAwMDAyMy0uMDAwMDMzLS4wMDAwMzRsLTYwLjQyODI1Ni01OC45NTc0NTFjLS42NDQxNi0uNjI4NDgxLTEuNjg4NTUtLjYyODQ4MS0yLjMzMjcxIDAtLjAwMDAwNC4wMDAwMDQtLjAwMDAwOC4wMDAwMDctLjAwMDAxMi4wMDAwMTFsLTYwLjQyNjk2ODMgNTguOTU3NDA4Yy0yLjU3NjYxNDEgMi41MTM5NDctNi43NTQxNzQ2IDIuNTEzOTktOS4zMzA4NDA4LjAwMDA5Mi0uMDAwMDE1MS0uMDAwMDE0LS4wMDAwMzA5LS4wMDAwMjktLjAwMDA0NjctLjAwMDA0NmwtODUuMTQzODY3NzQtODMuMDcxNDYzYy0yLjU3NjYzOTI4LTIuNTEzOTIxLTIuNTc2NjM5MjgtNi41ODk3OTUgMC05LjEwMzcxNjNsMTguODgyMzEyNjQtMTguNDIyNjk1NWMyLjU3NjYzOTMtMi41MTM5MjIyIDYuNzU0MTk5My0yLjUxMzkyMjIgOS4zMzA4Mzk3IDBsNjAuNDI5MTM0NyA1OC45NTgyNzU4Yy42NDQxNjA4LjYyODQ4IDEuNjg4NTQ5NS42Mjg0OCAyLjMzMjcxMDMgMCAuMDAwMDA5NS0uMDAwMDA5LjAwMDAxODItLjAwMDAxOC4wMDAwMjc3LS4wMDAwMjVsNjAuNDI2MTA2NS01OC45NTgyNTA4YzIuNTc2NTgxLTIuNTEzOTggNi43NTQxNDItMi41MTQwNzQzIDkuMzMwODQtLjAwMDIxMDMuMDAwMDM3LjAwMDAzNTQuMDAwMDcyLjAwMDA3MDkuMDAwMTA3LjAwMDEwNjNsNjAuNDI5MDU2IDU4Ljk1ODM1NDhjLjY0NDE1OS42Mjg0NzkgMS42ODg1NDkuNjI4NDc5IDIuMzMyNzA5IDBsNjAuNDI4MDc5LTU4Ljk1NzE5MjVjMi41NzY2NC0yLjUxMzkyMzEgNi43NTQxOTktMi41MTM5MjMxIDkuMzMwODM5IDB6IiBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9Im5vbnplcm8iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDk4IDE2MCkiLz48L2c+PC9zdmc+",
|
||||
desc: "Connect with immutable Passport",
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -18,8 +18,8 @@ import { notification } from 'ant-design-vue';
|
||||
import { createPinia } from 'pinia'
|
||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||
|
||||
import {PassportWallet} from '@/wallet/passPort';
|
||||
const passPortCallback = new PassportWallet()
|
||||
import { BlockChain } from '@/components/chain/BlockChain';
|
||||
new BlockChain().preparePassport();
|
||||
|
||||
const pinia = createPinia()
|
||||
pinia.use(piniaPluginPersistedstate)
|
||||
@ -40,6 +40,5 @@ app
|
||||
.use(VueAnimXyz)
|
||||
.use(vue3dLoader)
|
||||
.use(Antd)
|
||||
.use(passPortCallback)
|
||||
.use(router)
|
||||
.mount("#app");
|
||||
|
28
src/utils/model.util.js
Normal file
28
src/utils/model.util.js
Normal file
@ -0,0 +1,28 @@
|
||||
import {ref, render, createVNode} from 'vue'
|
||||
import { Deferred } from './promise.util';
|
||||
|
||||
// 动态创建Component, 并append至body, 返回一个对象, 用于调用Component的方法
|
||||
export const createModal = (Component, props) => {
|
||||
const visible = ref(false);
|
||||
props.visible = visible;
|
||||
const container = document.createElement('div')
|
||||
document.body.appendChild(container)
|
||||
const deferred = new Deferred();
|
||||
const show = () => {
|
||||
visible.value = true;
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
const close = (result) => {
|
||||
visible.value = false;
|
||||
container.remove();
|
||||
deferred.resolve(result);
|
||||
};
|
||||
props.close = close;
|
||||
const vnode = createVNode(Component, props)
|
||||
render(vnode, container)
|
||||
return {
|
||||
close,
|
||||
show
|
||||
}
|
||||
}
|
69
src/utils/promise.util.js
Normal file
69
src/utils/promise.util.js
Normal file
@ -0,0 +1,69 @@
|
||||
function retry(promiseFn, options) {
|
||||
let retries = 0;
|
||||
let defaultOptions = {
|
||||
maxRetries: 3,
|
||||
whitelistErrors: []
|
||||
};
|
||||
Object.assign(defaultOptions, options);
|
||||
const { maxRetries, whitelistErrors } = options;
|
||||
const retryPromise = async () => {
|
||||
try {
|
||||
return await promiseFn();
|
||||
} catch (err) {
|
||||
if (retries < maxRetries && whitelistErrors.some((whitelistedError) => err instanceof whitelistedError.constructor)) {
|
||||
retries++;
|
||||
return retryPromise();
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
return retryPromise();
|
||||
}
|
||||
var Deferred = class {
|
||||
constructor() {
|
||||
this.promise = new Promise((resolve, reject) => {
|
||||
this._resolve = resolve;
|
||||
this._reject = reject;
|
||||
});
|
||||
}
|
||||
resolve(value) {
|
||||
this._resolve(value);
|
||||
}
|
||||
reject(reason) {
|
||||
this._reject(reason);
|
||||
}
|
||||
then(onfulfilled, onrejected) {
|
||||
return this.promise.then(onfulfilled, onrejected);
|
||||
}
|
||||
catch(onrejected) {
|
||||
return this.promise.catch(onrejected);
|
||||
}
|
||||
};
|
||||
var PromiseQueue = class {
|
||||
constructor({ concurrency = 2 }) {
|
||||
this._current = 0;
|
||||
this._list = [];
|
||||
this.concurrency = concurrency;
|
||||
}
|
||||
add(promiseFn) {
|
||||
this._list.push(promiseFn);
|
||||
this.loadNext();
|
||||
}
|
||||
loadNext() {
|
||||
if (this._list.length === 0 || this.concurrency === this._current)
|
||||
return;
|
||||
this._current++;
|
||||
const fn = this._list.shift();
|
||||
const promise = fn.call(this);
|
||||
promise.then(this.onLoaded.bind(this)).catch(this.onLoaded.bind(this));
|
||||
}
|
||||
onLoaded() {
|
||||
this._current--;
|
||||
this.loadNext();
|
||||
}
|
||||
};
|
||||
export {
|
||||
Deferred,
|
||||
PromiseQueue,
|
||||
retry
|
||||
};
|
@ -27,7 +27,7 @@ class LPassportWallet {
|
||||
disableBlockedPopupOverlay: false, // Set to true to disable the blocked pop-up overlay
|
||||
}
|
||||
});
|
||||
this.passportInstance.loginCallback();
|
||||
this.passportInstance.loginCallback().then(()=>{}).catch(err=>{});
|
||||
this.client = new orderbook.Orderbook({ baseConfig });
|
||||
}
|
||||
async initWidget() {
|
||||
@ -55,8 +55,6 @@ class LPassportWallet {
|
||||
connect.mount('wallet');
|
||||
}
|
||||
async connect() {
|
||||
// const profile = await this.passportInstance.login();
|
||||
// console.log(profile,'-----------------------------------------------------------------')
|
||||
const passportProvider = this.passportInstance.connectEvm();
|
||||
this.web3Provider = new providers.Web3Provider(passportProvider);
|
||||
this.signer = this.web3Provider.getSigner();
|
||||
|
Loading…
x
Reference in New Issue
Block a user