From bdc37a40ff9e5853ae12d237e35266ae00c0281d Mon Sep 17 00:00:00 2001 From: D Date: Fri, 20 Sep 2024 18:08:37 +0500 Subject: [PATCH 1/6] chore(icp): Added to mainnet --- src/factory/config.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/factory/config.ts b/src/factory/config.ts index a1c2cf6e..f340e5d2 100644 --- a/src/factory/config.ts +++ b/src/factory/config.ts @@ -171,6 +171,14 @@ export namespace ChainFactoryConfigs { Tezos: new TezosToolkit("https://mainnet.ecadinfra.com"), tzktApi: "https://api.tzkt.io/", }, + icpParams: { + agent: new HttpAgent({ + host: "https://ic0.app", + }), + bridge: Principal.fromText("6gfde-pqaaa-aaaal-al76q-cai"), + identifier: "ICP", + storage, + }, } satisfies Partial; } } From 3120ae805af24f2e95d8fb749a9621cc8b9d5677 Mon Sep 17 00:00:00 2001 From: Muhammad Usman Date: Mon, 23 Sep 2024 18:02:36 +0500 Subject: [PATCH 2/6] fix(icp): send metaDataUri in lockNft. update types --- src/contractsTypes/icp/bridge/bridge.ts | 6 +++++- src/contractsTypes/icp/bridge/bridge.types.ts | 6 +++++- src/handlers/icp/index.ts | 10 +++++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/contractsTypes/icp/bridge/bridge.ts b/src/contractsTypes/icp/bridge/bridge.ts index 54ee213c..8c78ce07 100644 --- a/src/contractsTypes/icp/bridge/bridge.ts +++ b/src/contractsTypes/icp/bridge/bridge.ts @@ -42,6 +42,8 @@ export const idlFactory = ({ IDL }) => { 'destination_chain' : IDL.Text, 'token_id' : IDL.Nat, 'source_nft_contract_address' : IDL.Principal, + 'sender_address' : IDL.Text, + 'metadata_uri' : IDL.Text, 'nft_type' : IDL.Text, 'destination_user_address' : IDL.Text, }); @@ -93,12 +95,14 @@ export const idlFactory = ({ IDL }) => { [IDL.Opt(ClaimedEvent)], ['query'], ), + 'get_hash_from_nonce' : IDL.Func([IDL.Nat], [IDL.Opt(IDL.Text)], ['query']), 'get_locked_data' : IDL.Func([IDL.Text], [IDL.Opt(LockedEvent)], ['query']), + 'get_nonce' : IDL.Func([], [IDL.Nat], ['query']), 'get_validator' : IDL.Func([IDL.Text], [IDL.Opt(Validator)], ['query']), 'get_validator_count' : IDL.Func([], [IDL.Nat], ['query']), 'init' : IDL.Func([], [], []), 'lock_nft' : IDL.Func( - [IDL.Principal, IDL.Nat, IDL.Text, IDL.Text], + [IDL.Principal, IDL.Nat, IDL.Text, IDL.Text, IDL.Text], [IDL.Text], [], ), diff --git a/src/contractsTypes/icp/bridge/bridge.types.ts b/src/contractsTypes/icp/bridge/bridge.types.ts index 848cc0eb..21647150 100644 --- a/src/contractsTypes/icp/bridge/bridge.types.ts +++ b/src/contractsTypes/icp/bridge/bridge.types.ts @@ -37,6 +37,8 @@ export interface LockedEvent { 'destination_chain' : string, 'token_id' : bigint, 'source_nft_contract_address' : Principal, + 'sender_address' : string, + 'metadata_uri' : string, 'nft_type' : string, 'destination_user_address' : string, } @@ -63,11 +65,13 @@ export interface XPBridge { 'encode_claim_data' : ActorMethod<[ClaimData], Uint8Array | number[]>, 'get_blacklisted_validators' : ActorMethod<[string], [] | [boolean]>, 'get_claimed_data' : ActorMethod<[string], [] | [ClaimedEvent]>, + 'get_hash_from_nonce' : ActorMethod<[bigint], [] | [string]>, 'get_locked_data' : ActorMethod<[string], [] | [LockedEvent]>, + 'get_nonce' : ActorMethod<[], bigint>, 'get_validator' : ActorMethod<[string], [] | [Validator]>, 'get_validator_count' : ActorMethod<[], bigint>, 'init' : ActorMethod<[], undefined>, - 'lock_nft' : ActorMethod<[Principal, bigint, string, string], string>, + 'lock_nft' : ActorMethod<[Principal, bigint, string, string, string], string>, } export interface _SERVICE extends XPBridge {} export declare const idlFactory: IDL.InterfaceFactory; diff --git a/src/handlers/icp/index.ts b/src/handlers/icp/index.ts index 432cd271..92f2a57a 100644 --- a/src/handlers/icp/index.ts +++ b/src/handlers/icp/index.ts @@ -256,7 +256,14 @@ export async function icpHandler({ getStorageContract() { return storage; }, - async lockNft(signer, sourceNft, destinationChain, to, tokenId) { + async lockNft( + signer, + sourceNft, + destinationChain, + to, + tokenId, + metaDataUri, + ) { const bcWithSigner = await createBridgeActor(bridge, { agent: signer, }); @@ -265,6 +272,7 @@ export async function icpHandler({ tokenId, destinationChain, to, + metaDataUri, ); return { hash: () => hash, From f17f0b0a31c39f513169f8d31c5ff1eaab8b2469 Mon Sep 17 00:00:00 2001 From: D Date: Tue, 24 Sep 2024 15:14:28 +0500 Subject: [PATCH 3/6] chore(icp): new contract types --- src/contractsTypes/icp/bridge/bridge.ts | 6 ++++++ src/contractsTypes/icp/bridge/bridge.types.ts | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/contractsTypes/icp/bridge/bridge.ts b/src/contractsTypes/icp/bridge/bridge.ts index 8c78ce07..96b03cd1 100644 --- a/src/contractsTypes/icp/bridge/bridge.ts +++ b/src/contractsTypes/icp/bridge/bridge.ts @@ -90,11 +90,17 @@ export const idlFactory = ({ IDL }) => { [IDL.Opt(IDL.Bool)], ['query'], ), + 'get_claim_nonce' : IDL.Func([], [IDL.Nat], ['query']), 'get_claimed_data' : IDL.Func( [IDL.Text], [IDL.Opt(ClaimedEvent)], ['query'], ), + 'get_hash_from_claim_nonce' : IDL.Func( + [IDL.Nat], + [IDL.Opt(IDL.Text)], + ['query'], + ), 'get_hash_from_nonce' : IDL.Func([IDL.Nat], [IDL.Opt(IDL.Text)], ['query']), 'get_locked_data' : IDL.Func([IDL.Text], [IDL.Opt(LockedEvent)], ['query']), 'get_nonce' : IDL.Func([], [IDL.Nat], ['query']), diff --git a/src/contractsTypes/icp/bridge/bridge.types.ts b/src/contractsTypes/icp/bridge/bridge.types.ts index 21647150..8e36e577 100644 --- a/src/contractsTypes/icp/bridge/bridge.types.ts +++ b/src/contractsTypes/icp/bridge/bridge.types.ts @@ -64,7 +64,9 @@ export interface XPBridge { >, 'encode_claim_data' : ActorMethod<[ClaimData], Uint8Array | number[]>, 'get_blacklisted_validators' : ActorMethod<[string], [] | [boolean]>, + 'get_claim_nonce' : ActorMethod<[], bigint>, 'get_claimed_data' : ActorMethod<[string], [] | [ClaimedEvent]>, + 'get_hash_from_claim_nonce' : ActorMethod<[bigint], [] | [string]>, 'get_hash_from_nonce' : ActorMethod<[bigint], [] | [string]>, 'get_locked_data' : ActorMethod<[string], [] | [LockedEvent]>, 'get_nonce' : ActorMethod<[], bigint>, From ed3fd10e2e5dd19fa5dd7c708514b8ac70aa7433 Mon Sep 17 00:00:00 2001 From: Muhammad Usman Date: Thu, 19 Sep 2024 17:58:07 +0500 Subject: [PATCH 4/6] fix(mx): nftData uri issue. add getTransactionStatus, fix fetchHttpOrIpfs get image issue --- src/handlers/multiversx/index.ts | 7 +++++- src/handlers/multiversx/types.ts | 7 +++++- src/handlers/utils/fetchHttpOrIpfs.ts | 32 +++++++++++++++++++++------ 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/handlers/multiversx/index.ts b/src/handlers/multiversx/index.ts index c553390a..8b1bef80 100644 --- a/src/handlers/multiversx/index.ts +++ b/src/handlers/multiversx/index.ts @@ -85,7 +85,7 @@ export function multiversxHandler({ ) ).data; return { - metaData: atob(response.uris[0]), + metaData: atob(response.uris[1]), royalties: response.royalties ?? 0, }; }; @@ -541,6 +541,11 @@ export function multiversxHandler({ ); return bal; }, + async getTransactionStatus(txHash) { + return (await waitForTransaction(txHash)).isSuccessful() + ? "success" + : "failed"; + }, }; } diff --git a/src/handlers/multiversx/types.ts b/src/handlers/multiversx/types.ts index 05c9c2ac..4351d463 100644 --- a/src/handlers/multiversx/types.ts +++ b/src/handlers/multiversx/types.ts @@ -68,7 +68,12 @@ export type TMultiversXHandler = TSingularNftChain< string > & ReadClaimed721Event & - ReadClaimed1155Event; + ReadClaimed1155Event & + TGetTransactionStatus; + +type TGetTransactionStatus = { + getTransactionStatus(txHash: string): Promise; +}; export type TMultiversXParams = { provider: INetworkProvider; diff --git a/src/handlers/utils/fetchHttpOrIpfs.ts b/src/handlers/utils/fetchHttpOrIpfs.ts index 458ed159..7443f9e0 100644 --- a/src/handlers/utils/fetchHttpOrIpfs.ts +++ b/src/handlers/utils/fetchHttpOrIpfs.ts @@ -1,17 +1,35 @@ import axios from "axios"; -export async function fetchHttpOrIpfs(uri: string) { +async function fetchWithFallback(uri: string, fallbackUri: string) { const http = axios.create(); + try { + const response = await http.get(uri, { timeout: 10000 }); + return response.data; + } catch (ex) { + try { + const response = await http.get(fallbackUri, { timeout: 10000 }); + return response.data; + } catch (ex) { + return ""; + } + } +} + +export async function fetchHttpOrIpfs(uri: string) { const url = new URL(uri); if (url.protocol === "http:" || url.protocol === "https:") { - const response = await http.get(uri); - return response.data; + return fetchWithFallback( + uri, + `${uri.replace("ipfs.io", "xpnetwork.infura-ipfs.io")}`, + ); } if (url.protocol === "ipfs:") { - const response = await http.get( - `https://ipfs.io/ipfs/${uri.replace("ipfs://", "")}`, - ); - return response.data; + const ipfsUri = `https://ipfs.io/ipfs/${uri.replace("ipfs://", "")}`; + const fallbackIpfsUri = `https://xpnetwork.infura-ipfs.io/ipfs/${uri.replace( + "ipfs://", + "", + )}`; + return fetchWithFallback(ipfsUri, fallbackIpfsUri); } throw new Error("Unsupported protocol"); } From e80ceeed2ee3adb87e56f7e6d23edca60c7324a8 Mon Sep 17 00:00:00 2001 From: D Date: Wed, 2 Oct 2024 05:00:52 +0500 Subject: [PATCH 5/6] chore(chain): fixes --- src/factory/config.ts | 8 ++-- src/handlers/evm/index.ts | 18 +++++++++ src/handlers/evm/types.ts | 3 +- src/handlers/gasFactories/polygon.ts | 29 ++++++++++++++ src/handlers/gasFactories/utils.ts | 60 ++++++++++++++++++++++++++++ src/handlers/icp/index.ts | 2 +- 6 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 src/handlers/gasFactories/polygon.ts create mode 100644 src/handlers/gasFactories/utils.ts diff --git a/src/factory/config.ts b/src/factory/config.ts index f340e5d2..9947245e 100644 --- a/src/factory/config.ts +++ b/src/factory/config.ts @@ -80,10 +80,10 @@ export namespace ChainFactoryConfigs { storage, }, tezosParams: { - bridge: "KT1Fh6VH8BxA9xgJCn8hGZRxoo2vY3hrbqeV", + bridge: "KT1Gm6qaUmfuVnGJmfY46K6hiUzgFP8DLcke", identifier: "TEZOS", storage, - Tezos: new TezosToolkit("https://rpc.ghostnet.teztnets.com"), + Tezos: new TezosToolkit("https://ghostnet.ecadinfra.com"), tzktApi: "https://api.ghostnet.tzkt.io/", }, multiversxParams: { @@ -126,7 +126,7 @@ export namespace ChainFactoryConfigs { return { bscParams: { identifier: Chain.BSC, - provider: new JsonRpcProvider("https://bsc-pokt.nodies.app"), + provider: new JsonRpcProvider("https://binance.llamarpc.com"), bridge: ethers.getAddress("0x289FDdDce5119C41B82C969135212061D5E7Dce5"), royaltySalePrice: 10000, storage, @@ -165,7 +165,7 @@ export namespace ChainFactoryConfigs { storage, }, tezosParams: { - bridge: "KT1N3qtcfxzNMhdRMphvtDCKLEDwVLhZ8Cpq", + bridge: "KT1M4hZZG2zcRT1aohZsSmXcoeAVpwG9Xz3N", identifier: Chain.TEZOS, storage, Tezos: new TezosToolkit("https://mainnet.ecadinfra.com"), diff --git a/src/handlers/evm/index.ts b/src/handlers/evm/index.ts index 7805fa18..1d467437 100644 --- a/src/handlers/evm/index.ts +++ b/src/handlers/evm/index.ts @@ -3,6 +3,7 @@ import { ERC721Royalty__factory, ERC1155Royalty__factory, } from "../../contractsTypes/evm"; +import { getPolygonGas } from "../gasFactories/polygon"; import { retryFn } from "../utils"; import { TEvmHandler, TEvmParams } from "./types"; @@ -17,6 +18,23 @@ export function evmHandler({ return { identifier, async claimNft(wallet, claimData, sigs, extraArgs) { + if (identifier === "MATIC") { + const gas = await getPolygonGas(); + const contract = Bridge__factory.connect(bridge, wallet); + const ret = await contract.claimNFT721( + claimData, + sigs.map((e) => e.signature), + { + ...extraArgs, + ...gas, + value: claimData.fee, + }, + ); + return { + ret: ret, + hash: () => ret.hash, + }; + } const contract = Bridge__factory.connect(bridge, wallet); const ret = await contract.claimNFT721( claimData, diff --git a/src/handlers/evm/types.ts b/src/handlers/evm/types.ts index 92b19f4b..d18c5384 100644 --- a/src/handlers/evm/types.ts +++ b/src/handlers/evm/types.ts @@ -4,6 +4,7 @@ import { Overrides, Provider, Signer, + Wallet, } from "ethers"; import { Bridge, BridgeStorage } from "../../contractsTypes/evm"; @@ -36,7 +37,7 @@ export type TEvmHandler = TNftChain< PayableOverrides, ContractTransactionResponse > & - TApproveNFT & + TApproveNFT & DeployCollection< Signer, { diff --git a/src/handlers/gasFactories/polygon.ts b/src/handlers/gasFactories/polygon.ts new file mode 100644 index 00000000..4a302088 --- /dev/null +++ b/src/handlers/gasFactories/polygon.ts @@ -0,0 +1,29 @@ +import axios from "axios"; +import { + GAS_LIMIT, + TGas, + convertToGwei, + getConstantGas, + getGas, +} from "./utils"; + +const getConstantGasForPolygon = (): TGas => getConstantGas(800); + +const getGasFromGasStation = async (): Promise => { + const response = await axios.get("https://gasstation.polygon.technology/v2"); + console.log("polygon gas response", response.data); + + const gas = convertToGwei(String(response?.data?.fast.maxFee)); + + return { + maxPriorityFeePerGas: gas, + maxFeePerGas: gas, + gasLimit: GAS_LIMIT, + }; +}; + +export const getPolygonGas = async (): Promise => { + const gas = await getGas(getGasFromGasStation, getConstantGasForPolygon); + console.log({ gas }, "gas in internal polygon"); + return gas; +}; diff --git a/src/handlers/gasFactories/utils.ts b/src/handlers/gasFactories/utils.ts new file mode 100644 index 00000000..7b40bd5e --- /dev/null +++ b/src/handlers/gasFactories/utils.ts @@ -0,0 +1,60 @@ +import { BigNumberish as EthersBigNumber, ethers } from "ethers"; + +export type TGas = { + maxPriorityFeePerGas: EthersBigNumber; + maxFeePerGas: EthersBigNumber; + gasLimit: number; +}; + +type TArgs = [ + getGasStationGas: () => Promise, + getConstantGas: () => TGas, +]; + +type TGetGas = (...args: TArgs) => Promise; + +export const GAS_LIMIT = 5_000_000; + +export type TCreateGasConfig = { + chainNonce: number; + gasToAdd: number; + constantGas: number; + gasStationEndpoint: string; +}; + +export const convertToGwei = (value: string): EthersBigNumber => { + return ethers.parseUnits(value, "gwei"); +}; + +export const getConstantGas = (fee: number): TGas => { + const maxPriorityFeePerGas = convertToGwei(`${fee}`); + const maxFeePerGas = convertToGwei(`${fee}`); + return { + maxPriorityFeePerGas, + maxFeePerGas, + gasLimit: GAS_LIMIT, + }; +}; + +export const getGas: TGetGas = async (getGasStationGas, getConstantGas) => { + let retriesForGettingGas = 0; + while (retriesForGettingGas < 5) { + try { + return await getGasStationGas(); + } catch (error) { + console.log("error when getting gas for", error); + if (retriesForGettingGas === 4) { + return getConstantGas(); + } + await sleep(5_000); + retriesForGettingGas++; + } + } + return getConstantGas(); +}; + +export function sleep(ms: number) { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); +} diff --git a/src/handlers/icp/index.ts b/src/handlers/icp/index.ts index 92f2a57a..4b07cd21 100644 --- a/src/handlers/icp/index.ts +++ b/src/handlers/icp/index.ts @@ -285,7 +285,7 @@ export async function icpHandler({ agent: signer, }); await lc.icrc2_approve({ - amount: BigInt(claimData.fee + 10_000n), + amount: BigInt(claimData.fee + 10_000n + 14638409n), spender: { owner: bridge, subaccount: [], From fe6626ac8e872b54ada232b343e6f70b368592af Mon Sep 17 00:00:00 2001 From: D Date: Wed, 2 Oct 2024 05:36:09 +0500 Subject: [PATCH 6/6] chore(tezos): new contract --- src/factory/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/factory/config.ts b/src/factory/config.ts index 9947245e..ea698171 100644 --- a/src/factory/config.ts +++ b/src/factory/config.ts @@ -165,7 +165,7 @@ export namespace ChainFactoryConfigs { storage, }, tezosParams: { - bridge: "KT1M4hZZG2zcRT1aohZsSmXcoeAVpwG9Xz3N", + bridge: "KT1UMVUP3XBpPrMUwuC6DXjEcLgZykV7p1PW", identifier: Chain.TEZOS, storage, Tezos: new TezosToolkit("https://mainnet.ecadinfra.com"),