diff --git a/README.md b/README.md index 93269253..b820fe0d 100644 --- a/README.md +++ b/README.md @@ -792,3 +792,12 @@ P.S. The library is a work in progress. More features will be added soon. console.log(`The estimated fee on Tezos is: ${feeEstimation} Algos`); })(); ``` + +## Enabling Bridge version 3 transfers (early beta) + +To implement v3 transfers for chain: + +1. Specify _v3_chainId_ for the chain in src/consts.ts +2. Specify _v3_bridge_ contract address for the chain params in src/factory/factories.ts +3. Implement _getTokenInfo, getClaimData, lockNFT, claimV3NFT_ methods for the chain helper (see examples - src/helpers/elrond/elrond.ts, src/helpers/evm/web3.ts) +4. In order to allow UI to identify NFT origin chain implement _getNftOrigin_ for the chain helper diff --git a/src/factory/factories.ts b/src/factory/factories.ts index 0d49ef17..cbdf64f7 100644 --- a/src/factory/factories.ts +++ b/src/factory/factories.ts @@ -94,6 +94,7 @@ export namespace ChainFactoryConfigs { }) ), nonce: Chain.TON, + proxy: "https://sheltered-crag-76748.herokuapp.com/", bridgeAddr: "kQBwUu-b4O6qDYq3iDRvsYUnTD6l3WCxLXkv0aH6ywAaPs3c", burnerAddr: "kQCbH9gGgqJzXuusUVajW_40brrl2fxTYqMkk6HUhJnIgOQA", xpnftAddr: "EQDji0YH-SNT-qi6o5dQQBLeWL0Xmm46fnqj34EYhOL34WDc", @@ -562,6 +563,7 @@ export namespace ChainFactoryConfigs { bridgeAddr: "kQAhrkiW7pA5eE_7vtz7_AQhHznfqR0VFyTGs4mgyaVLPgfG", burnerAddr: "kQBo5aNuDXghpZ2u9yMdfaR9oVQEuRddNLCoNg8YgI_k2MOE", notifier, + proxy: "https://sheltered-crag-76748.herokuapp.com/", nonce: Chain.TON, tonweb: new TonWeb( new TonWeb.HttpProvider("https://toncenter.com/api/v2/jsonRPC", { @@ -871,6 +873,7 @@ export namespace ChainFactoryConfigs { bridgeAddr: "kQBpucKquLw9uwGfLe_KHt65YWnchjoY2VPSsKDTI7JqrcLm", burnerAddr: "kQBR45AvvaO9a-rGfVkR0INx3JwoR-HngYA3tfctlGM1_Ml7", notifier, + proxy: "https://sheltered-crag-76748.herokuapp.com/", tonweb: new TonWeb( new TonWeb.HttpProvider("https://toncenter.com/api/v2/jsonRPC", { apiKey: diff --git a/src/helpers/elrond/elrond-test.ts b/src/helpers/elrond/elrond-test.ts index 21da39ed..e093194c 100644 --- a/src/helpers/elrond/elrond-test.ts +++ b/src/helpers/elrond/elrond-test.ts @@ -31,7 +31,7 @@ import BigNumber from "bignumber.js"; //import { inspect } from "node:util"; const f = Mnemonic.fromString( - `evidence liberty culture stuff canal minute toward trash boil cry verb recall during citizen social upper budget ranch distance business excite fox icon tool` + `` ); const proxyNetworkProvider = new ProxyNetworkProvider("https://devnet-gateway.multiversx.com"); const apiNetworkProvider = new ApiNetworkProvider("https://devnet2-api.multiversx.com"); diff --git a/src/helpers/elrond/elrond.ts b/src/helpers/elrond/elrond.ts index 6ae8e103..4a542366 100644 --- a/src/helpers/elrond/elrond.ts +++ b/src/helpers/elrond/elrond.ts @@ -993,8 +993,6 @@ export async function elrondHelperFactory( return ""; }, async getTokenInfo(depTrxData) { - console.log(depTrxData, "depTrxData"); - const nftData = await multiversexApiService.getTokenInfo( depTrxData.sourceNftContractAddress, Number(depTrxData.tokenId).toString(16) @@ -1004,8 +1002,6 @@ export async function elrondHelperFactory( depTrxData.sourceNftContractAddress ); - console.log(collectionData, "collectionData"); - return { metadata: Base64.decode(nftData?.uris?.at(1) || ""), name: collectionData.name, @@ -1025,7 +1021,6 @@ export async function elrondHelperFactory( if (!sourceNonce) { throw new Error("Source chain is undefined"); } - console.log(sourceNonce, "sourceNonce in elrond"); const sourceChainHelper = helpers.get(sourceNonce as ChainNonce); diff --git a/src/helpers/evm/web3.ts b/src/helpers/evm/web3.ts index 235ad1e5..5383cfa4 100644 --- a/src/helpers/evm/web3.ts +++ b/src/helpers/evm/web3.ts @@ -1133,7 +1133,6 @@ export async function web3HelperFactory( if (!sourceNonce) { throw new Error("Source chain is undefined"); } - console.log(sourceNonce, "sourceNonce"); const sourceChain = helpers.get(sourceNonce as ChainNonce); @@ -1189,11 +1188,7 @@ export async function web3HelperFactory( console.log(e.message); return []; }); - console.log( - signatures, - transactionHash, - CHAIN_INFO.get(from.getNonce())?.v3_chainId! - ); + if (signatures.length < sigNumber) return getSignatures(tryNumber + 1); return signatures; }; @@ -1224,8 +1219,6 @@ export async function web3HelperFactory( } ); - console.log(trx); - const tx = await signer.sendTransaction(trx); await tx.wait(); diff --git a/src/helpers/ton/ton.ts b/src/helpers/ton/ton.ts index 69a6cc6f..08c49886 100644 --- a/src/helpers/ton/ton.ts +++ b/src/helpers/ton/ton.ts @@ -17,8 +17,11 @@ import { BalanceCheck, GetExtraFees, WhitelistCheck, - //GetClaimData, + GetClaimData, + LockNFT, GetTokenInfo, + DepTrxData, + TokenInfo, } from "../chain"; import { ChainNonce, PreTransfer, ClaimV3NFT } from "../.."; @@ -38,16 +41,15 @@ import base64url from "base64url"; import { TonClient, Address, beginCell, Dictionary } from "newton"; -//import { sign } from "ton-crypto"; import { ClaimData, storeClaimData, SignerAndSignature, - //ClaimNFT721, storeClaimNFT721, NftItem, NftCollection, } from "./v3types"; + import { CHAIN_INFO } from "../../consts"; export type TonSigner = { @@ -93,13 +95,16 @@ export type TonHelper = ChainNonceGet & NftListUtils & ScVerifyUtils & ClaimV3NFT & - GetTokenInfo; + GetTokenInfo & + GetClaimData & + LockNFT; export type TonParams = { tonweb: TonWeb; notifier: EvNotifier; nonce: ChainNonce; bridgeAddr: string; + proxy: string; burnerAddr: string; xpnftAddr: string; feeMargin: FeeMargins; @@ -501,8 +506,28 @@ export async function tonHelper(args: TonParams): Promise { getScVerifyAddr(address) { return address.replace(/[^a-zA-Z0-9]/g, ""); }, + //TODO: complete getClaimData method for TON + async getClaimData(hash, helpers) { + hash; + //TODO: fetch and decode TON trx; + const decoded = {} as DepTrxData; + + const sourceNonce = Array.from(CHAIN_INFO.values()).find( + (c) => c.v3_chainId === decoded.sourceChain + )?.nonce; + + const sourceChainHelper = helpers.get(sourceNonce as ChainNonce); + + const tokenInfo: TokenInfo = await ( + sourceChainHelper as any + ).getTokenInfo(decoded); + + return { + ...tokenInfo, + ...decoded, + }; + }, async getTokenInfo(depTrxData) { - console.log(args.tonweb.provider.host, "host"); const client = new TonClient({ endpoint: args.tonweb.provider.host, apiKey: args.tonweb.provider.options.apiKey, @@ -510,39 +535,63 @@ export async function tonHelper(args: TonParams): Promise { const addr = Address.parseFriendly( depTrxData.sourceNftContractAddress ).address; - console.log(addr); + const nftItem = client.open(NftItem.fromAddress(addr)); const nftData = await nftItem.getGetNftData(); - console.log(nftData, "nftData"); + let metaDataURL: string = ""; + let royalty: string = "0"; + if (nftData.collection_address) { const nftCollection = client.open( NftCollection.fromAddress(nftData.collection_address) ); - - const { collection_content } = - await nftCollection.getGetCollectionData(); - const collectionContentSlice = collection_content.asSlice(); - collectionContentSlice.loadUint(8); - metaDataURL = collectionContentSlice.loadStringTail(); - console.log(metaDataURL, "metaDataURL"); + const [collectionData, royaltyData] = await Promise.allSettled([ + nftCollection.getGetCollectionData(), + nftCollection.getRoyaltyParams(), + ]); + + if (collectionData.status === "fulfilled") { + const { collection_content } = collectionData.value; + const collectionContentSlice = collection_content.asSlice(); + collectionContentSlice.loadUint(8); + metaDataURL = collectionContentSlice.loadStringTail(); + } + + if (royaltyData.status === "fulfilled") { + const royaltyParams = royaltyData.value; + const royaltyInNum = + royaltyParams.numerator / royaltyParams.denominator; + const standardRoyalty = royaltyInNum * BigInt(10); + royalty = standardRoyalty.toString(); + } + } else { + const individualContentSlice = nftData.individual_content.asSlice(); + individualContentSlice.loadBits(8); + metaDataURL = individualContentSlice.loadStringTail(); } - const individualContentSlice = nftData.individual_content.asSlice(); - individualContentSlice.loadBits(8); - metaDataURL = individualContentSlice.loadStringTail(); - const metaData = (await axios.get(metaDataURL)).data; + const metaData = ( + await axios.get( + typeof window !== "undefined" ? args.proxy + metaDataURL : metaDataURL + ) + ).data; console.log(metaData); return { name: metaData.name || "", symbol: "", - metadata: "", - royalty: "", - image: "", + metadata: metaDataURL, + royalty, + //image: "", }; }, + //TODO: lock trx in TON + async lockNFT(sender, toChain, id, receiver) { + console.log(sender, toChain, id, receiver); + return ""; + }, async claimV3NFT( sender, helpers,