Merge branch 'new-CounterFire' of http://git.kingsome.cn/huangjinming/CounterFireGames into new-CounterFire
This commit is contained in:
commit
a261563e36
5
.env.dev
5
.env.dev
@ -2,3 +2,8 @@ VUE_APP_BASE_API='https://market.cebg.games'
|
|||||||
VUE_APP_BASE_API2='https://invitation.counterfire.games'
|
VUE_APP_BASE_API2='https://invitation.counterfire.games'
|
||||||
//VUE_APP_BASE_API2='http://192.168.100.83:3000/'
|
//VUE_APP_BASE_API2='http://192.168.100.83:3000/'
|
||||||
VUE_APP_GPAL_API='https://game2006api.cebggame.com/'
|
VUE_APP_GPAL_API='https://game2006api.cebggame.com/'
|
||||||
|
VUE_APP_PASSPORT_PUBLISHABLE_KEY=pk_imapik-test-8c2FAlWxWAoRITk1v9rH
|
||||||
|
VUE_APP_PASSPORT_REDIRECT_URI=http://localhost:4000/redirect
|
||||||
|
VUE_APP_PASSPORT_LOGOUT_URI=http://localhost:4000/
|
||||||
|
VUE_APP_PASSPORT_CLIENT_ID=eTmUah69p7ZdRhRYzBta6lZRKXXeXDYj
|
||||||
|
VUE_APP_PASSPORT_MARKET_ADDRESS=0x7d117aA8BD6D31c4fa91722f246388f38ab1942c
|
5
.prettierignore
Normal file
5
.prettierignore
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
node_modules
|
||||||
|
artifacts
|
||||||
|
cache
|
||||||
|
coverage*
|
||||||
|
gasReporterOutput.json
|
8
.prettierrc
Normal file
8
.prettierrc
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 120,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"singleQuote": false,
|
||||||
|
"bracketSpacing": false,
|
||||||
|
"explicitTypes": "always"
|
||||||
|
}
|
22
jsconfig.json
Normal file
22
jsconfig.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"module": "esnext",
|
||||||
|
"baseUrl": "./",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"allowJs": true,
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lib": [
|
||||||
|
"esnext",
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"scripthost"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
@ -20,6 +20,7 @@
|
|||||||
"ant-design-vue": "^4.2.3",
|
"ant-design-vue": "^4.2.3",
|
||||||
"axios": "^1.3.3",
|
"axios": "^1.3.3",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
|
"ethers": "^5.7.2",
|
||||||
"gsap": "^3.11.5",
|
"gsap": "^3.11.5",
|
||||||
"js-cookie": "^3.0.1",
|
"js-cookie": "^3.0.1",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="wallet"></div>
|
||||||
<ChainModel></ChainModel>
|
<ChainModel></ChainModel>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -78,7 +79,7 @@ import { hasMetamask } from "@/utils/chain.util";
|
|||||||
import { useRouter, useRoute } from "vue-router";
|
import { useRouter, useRoute } from "vue-router";
|
||||||
import ChainModel from "@/components/home/ChainModel.vue";
|
import ChainModel from "@/components/home/ChainModel.vue";
|
||||||
import { useCopyToClipboard } from "./../../hooks/useCopyToClipboard";
|
import { useCopyToClipboard } from "./../../hooks/useCopyToClipboard";
|
||||||
import { getConnect } from "@/wallet/passPort"
|
import { PassportWallet } from "@/wallet/passPort"
|
||||||
|
|
||||||
const AppModule = useAppStore();
|
const AppModule = useAppStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -226,8 +227,13 @@ watchEffect(() => {
|
|||||||
const immuTableLogin = async () => {
|
const immuTableLogin = async () => {
|
||||||
// console.log('----')
|
// console.log('----')
|
||||||
try{
|
try{
|
||||||
const walletLogin = await getConnect()
|
const walletLogin = await new PassportWallet().connect()
|
||||||
console.log(walletLogin)
|
console.log(walletLogin)
|
||||||
|
// const list = await new PassportWallet().beginSellERC721({
|
||||||
|
// contractAddress: '',
|
||||||
|
// tokenId: ''
|
||||||
|
// });
|
||||||
|
// console.log(list)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
16
src/utils/singleton.js
Normal file
16
src/utils/singleton.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export const createSingleton = (Class) => {
|
||||||
|
let instance;
|
||||||
|
|
||||||
|
return new Proxy(Class, {
|
||||||
|
construct(target, args, newTarget) {
|
||||||
|
// Skip proxy for children
|
||||||
|
if (target.prototype !== newTarget.prototype) {
|
||||||
|
return Reflect.construct(target, argumentsList, newTarget)
|
||||||
|
}
|
||||||
|
if (!instance) {
|
||||||
|
instance = Reflect.construct(target, args, newTarget);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
@ -1,13 +1,25 @@
|
|||||||
import { config, passport } from '@imtbl/sdk';
|
import { config, passport, orderbook, checkout } from '@imtbl/sdk';
|
||||||
|
import { createSingleton } from '@/utils/singleton';
|
||||||
|
import { providers } from 'ethers';
|
||||||
|
|
||||||
const passportInstance = new passport.Passport({
|
const environment = process.env.NODE_ENV === 'production' ? config.Environment.PRODUCTION : config.Environment.SANDBOX;
|
||||||
baseConfig: {
|
const publishableKey = import.meta.env.VUE_APP_PASSPORT_PUBLISHABLE_KEY
|
||||||
environment: config.Environment.SANDBOX, // or Environment.PRODUCTION
|
const clientId = import.meta.env.VUE_APP_PASSPORT_CLIENT_ID
|
||||||
publishableKey: 'wc:b348768c53d32b69062adcc7f67b263f771564c39edc06acc4cb3e9ee561d415@2?relay-protocol=irn&symKey=b8302aed25de3f9e3485eb8601d27c52779ab28cd8b1398312aa18be01cebbe8', // replace with your publishable API key from Hub
|
const redirectUri = import.meta.env.VUE_APP_PASSPORT_REDIRECT_URI
|
||||||
},
|
const logoutRedirectUri = import.meta.env.VUE_APP_PASSPORT_LOGOUT_URI
|
||||||
clientId: '<YOUR_CLIENT_ID>', // replace with your client ID from Hub
|
const marketAddress = import.meta.env.VUE_APP_PASSPORT_MARKET_ADDRESS
|
||||||
redirectUri: 'http://192.168.100.216:4000/', // replace with one of your redirect URIs from Hub
|
|
||||||
logoutRedirectUri: 'http://192.168.100.216:4000/', // replace with one of your logout URIs from Hub
|
const NATIVE = 'NATIVE'
|
||||||
|
const ERC20 = 'ERC20'
|
||||||
|
|
||||||
|
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',
|
audience: 'platform_api',
|
||||||
scope: 'openid offline_access email transact',
|
scope: 'openid offline_access email transact',
|
||||||
popupOverlayOptions: {
|
popupOverlayOptions: {
|
||||||
@ -15,14 +27,248 @@ const passportInstance = new passport.Passport({
|
|||||||
disableBlockedPopupOverlay: false, // Set to true to disable the blocked pop-up overlay
|
disableBlockedPopupOverlay: false, // Set to true to disable the blocked pop-up overlay
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.passportInstance.loginCallback();
|
||||||
// 链接Wallet Connect钱包
|
this.client = new orderbook.Orderbook({ baseConfig });
|
||||||
export async function getConnect() {
|
|
||||||
// let result = await passportInstance.loginCallback()
|
|
||||||
const profile = await passportInstance.login();
|
|
||||||
console.log(profile,'-----------------------------------------------------------------')
|
|
||||||
return
|
|
||||||
// let result = profile.passport.UserProfile | null = await passportInstance.login()
|
|
||||||
// let result = await passportInstance.request({ method: 'eth_requestAccounts' })
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
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');
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
const accounts = await passportProvider.request({ method: "eth_requestAccounts" })
|
||||||
|
const accessToken = await this.passportInstance.getAccessToken();
|
||||||
|
console.log('accessToken:', accessToken)
|
||||||
|
// const idToken = await passportInstance.getIdToken();
|
||||||
|
// console.log('idToken:', idToken)
|
||||||
|
return {profile, accounts, accessToken}
|
||||||
|
}
|
||||||
|
|
||||||
|
async logout() {
|
||||||
|
await this.passportInstance.logout();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 查询某个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 { 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();
|
||||||
|
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 PassportWallet = createSingleton(LPassportWallet)
|
Loading…
x
Reference in New Issue
Block a user