123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- import { Web3Networks } from "./Web3Networks";
- export class Web3Result {
- universalProvider: any;
- evmProvider: any;
- // chainType: Web3Networks;
- account: any;
- _signer: any;
- paymentProvider: any;
- public get signer(): any {
- if (this._signer == null) {
- if (this.evmProvider != null && this.evmProvider.isCon) {
- this._signer = this.evmProvider.getSigner();
- }
- }
- return this._signer;
- }
- public set signer(signer: any) {
- this._signer = signer;
- }
- public get success(): boolean {
- if (this.account == null || this.account == "") {
- return false;
- }
- if (this.evmProvider == null) {
- return false;
- }
- return true;
- }
- public static async formatEther(balance: any): Promise<number> {
- // @ts-ignore
- return Number(Number(window.ethers.utils.formatEther(balance)).toFixed(8));
- }
- public async getBalance(): Promise<number> {
- const wei = await this.evmProvider.getBalance(this.account);
- return await Web3Result.formatEther(wei);
- }
- }
- export enum ContractResult {
- WalletConnectError = "wallet connect error",
- SUCCESS = "all success",
- NOT_OWNER = "not owner",
- NOT_APPROVED = "not approved",
- GAS_ERROR = "gas error",
- EXECUTION_ERROR = "execution error",
- }
- export interface ContractError extends Error {
- code?: string;
- data?: any;
- }
- export class Contract {
-
- private static readonly ERROR_NOT_OWNER = "not owner";
- private static readonly ERROR_NOT_APPROVED = "not approved";
- private static readonly ERROR_GAS = "gas error";
- private static readonly ERROR_EXECUTION = "execution error";
- private readonly web3Result: Web3Result;
- private readonly abi: any;
- private readonly contractAddress: string;
- private contract: any;
- private constructor(
- web3Result: Web3Result,
- abi: any,
- contractAddress: string
- ) {
- this.web3Result = web3Result;
- this.abi = abi;
- this.contractAddress = contractAddress;
- }
- public static async build(
- web3Result: Web3Result,
- abi: any,
- contractAddress: string
- ): Promise<Contract> {
- const contract = new Contract(web3Result, abi, contractAddress);
- await contract.initialize();
- return contract;
- }
- private async initialize(): Promise<void> {
- console.log("Contract initializing", this.contractAddress);
- // @ts-ignore
- this.contract = await new window.ethers.Contract(
- this.contractAddress,
- this.abi,
- this.web3Result.signer
- );
- }
- public async getContractBalance(){
- const balance = await this.contract.balanceOf(this.web3Result.account);
- console.log("balance", balance);
- let balanceNumber = await Web3Result.formatEther(balance);
- console.log("balanceNumber", balanceNumber);
- return balanceNumber;
- }
-
- private async isOwnerOf(tokenId: number): Promise<boolean> {
- console.log(
- "Checking ownership for token",
- tokenId,
- this.web3Result.account
- );
- const owner = await this.contract.ownerOf(tokenId);
- console.log("Ownership check result", owner, this.web3Result.account);
- return owner.toLowerCase() === this.web3Result.account.toLowerCase();
- }
- public async getAllTokensOfOwner(account: string): Promise<number[]> {
- try {
- // Get all Transfer events
- const filter = this.contract.filters.Transfer(null, account);
- const events = await this.contract.queryFilter(filter);
-
- // Also get transfers out to handle cases where tokens were transferred away
- const filterOut = this.contract.filters.Transfer(account, null);
- const eventsOut = await this.contract.queryFilter(filterOut);
-
- // Create a map to track current ownership
- const tokenMap = new Map<number, boolean>();
-
- // Process incoming transfers
- for (const event of events) {
- if (event.args) {
- const tokenId = event.args.tokenId.toNumber();
- tokenMap.set(tokenId, true);
- }
- }
-
- // Process outgoing transfers
- for (const event of eventsOut) {
- if (event.args) {
- const tokenId = event.args.tokenId.toNumber();
- tokenMap.delete(tokenId);
- }
- }
-
- // Convert map keys to array
- const tokenIds = Array.from(tokenMap.keys());
-
- console.log("Found tokens:", tokenIds);
- return tokenIds;
- } catch (error) {
- console.error("Get all tokens of owner failed:", error);
- return [];
- }
- }
- private async isApproved(
- tokenId: number,
- toAddress: string
- ): Promise<boolean> {
- console.log("Checking approval for token", tokenId, toAddress);
- const approvedAddress = await this.contract.getApproved(tokenId);
- console.log("Approval check result", approvedAddress, toAddress);
- return approvedAddress.toLowerCase() === toAddress.toLowerCase();
- }
- private async approve(tokenId: number, toAddress: string): Promise<boolean> {
- console.log("Approving token", tokenId, toAddress);
- try {
- const tx = await this.contract.approve(toAddress, tokenId);
- console.log("Approval transaction", tx);
- return true;
- } catch (error) {
- console.error("Approval failed:", error);
- return false;
- }
- }
- private async wallApproval(
- userAddress: string,
- receiveAddress: string,
- nftNo: number
- ) {
- console.log("Approval transaction", userAddress, receiveAddress, nftNo);
- const tx = this.contract.Approval(userAddress, receiveAddress, nftNo);
- console.log("Approval transaction", tx);
- return tx;
- }
- public async transferTo(
- userAddress: string,
- receiveAddress: string,
- nftNo: number
- ): Promise<ContractResult> {
- try {
- const fromAddress = userAddress.toLowerCase();
- const toAddress = receiveAddress.toLowerCase();
- // Then execute the transfer
- console.log("Executing transfer...");
- const transferTx = await this.contract.transferFrom(
- fromAddress,
- toAddress,
- nftNo
- );
- console.log("Transfer transaction hash:", transferTx.hash);
- await transferTx.wait();
- console.log("Transfer confirmed");
- return ContractResult.SUCCESS;
- } catch (error: any) {
- console.error("Transfer failed:", error);
- if (error.code === "INSUFFICIENT_FUNDS") {
- return ContractResult.GAS_ERROR;
- }
- return ContractResult.EXECUTION_ERROR;
- }
- }
- public async ownerAndApprove(
- tokenId: number,
- toAddress: string
- ): Promise<ContractResult> {
- console.log("Starting owner and approve check for token", tokenId);
- const isOwner = await this.isOwnerOf(tokenId);
- if (!isOwner) {
- return ContractResult.NOT_OWNER;
- }
- console.log("Ownership verified");
- const isApproved = await this.isApproved(tokenId, toAddress);
- if (!isApproved) {
- const approvalSuccess = await this.approve(tokenId, toAddress);
- if (!approvalSuccess) {
- return ContractResult.NOT_APPROVED;
- }
- }
- console.log("Approval verified");
- return ContractResult.SUCCESS;
- }
- public async burnSBTAndSoulNFT(
- sbtAddress: string,
- userId: number,
- sbtId: number,
- soulIds: number[]
- ): Promise<boolean> {
- try {
- const tx = await this.contract.fusionBurn(
- userId,
- sbtAddress,
- sbtId,
- soulIds
- );
- console.log("Burn SBT and Soul NFT transaction", tx);
- return true;
- } catch (error) {
- console.error("Burn SBT and Soul NFT failed:", error);
- return false;
- }
- }
- public async burnSBT(
- sbtAddress: string,
- userId: number,
- sbtId: number
- ): Promise<boolean> {
- try {
- const tx = await this.contract.burnNFT(sbtAddress, sbtId, userId);
- console.log("Burn SBT transaction", tx);
- return true;
- } catch (error) {
- console.error("Burn SBT failed:", error);
- return false;
- }
- }
- public async getBalanceOf(owner: string): Promise<number> {
- try {
- const balance = await this.contract.balanceOf(owner);
- return balance.toNumber();
- } catch (error) {
- console.error("Get balance failed:", error);
- return 0;
- }
- }
- public async getTokenOfOwnerByIndex(owner: string, index: number): Promise<number> {
- try {
- const tokenId = await this.contract.tokenOfOwnerByIndex(owner, index);
- return tokenId.toNumber();
- } catch (error) {
- console.error("Get token of owner by index failed:", error);
- return 0;
- }
- }
- public async getTokenURI(tokenId: number): Promise<string> {
- try {
- return await this.contract.tokenURI(tokenId);
- } catch (error) {
- console.error("Get token URI failed:", error);
- return "";
- }
- }
- }
|