diff --git a/.github/workflows/xcm-tests.yml b/.github/workflows/xcm-tests.yml index c72dad74..9f88256b 100644 --- a/.github/workflows/xcm-tests.yml +++ b/.github/workflows/xcm-tests.yml @@ -88,6 +88,7 @@ jobs: --parachain=configs/hydradx.yml \ --parachain=configs/acala.yml \ --parachain=configs/parallel.yml \ + --parachain=configs/bifrost-polkadot.yml \ &> log.txt & echo "Waiting for log to show chopsticks is ready..." tail -f log.txt | grep -q "Connected parachains" diff --git a/package.json b/package.json index f2c42510..9bc17318 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@interlay/bridge", - "version": "0.3.16", + "version": "0.4.0", "description": "polkawallet bridge sdk", "main": "build/index.js", "typings": "build/index.d.ts", diff --git a/scripts/interlay-chopsticks-test.ts b/scripts/interlay-chopsticks-test.ts index e9d78901..e40f9a2c 100644 --- a/scripts/interlay-chopsticks-test.ts +++ b/scripts/interlay-chopsticks-test.ts @@ -7,6 +7,7 @@ import { StatemintAdapter } from "../src/adapters/statemint"; import { HydraAdapter } from "../src/adapters/hydradx"; import { AcalaAdapter } from "../src/adapters/acala"; import { ParallelAdapter } from "../src/adapters/parallel"; +import { BifrostPolkadotAdapter } from "../src/adapters/bifrost"; import { BaseCrossChainAdapter } from "../src/base-chain-adapter"; import { RouterTestCase, runTestCasesAndExit } from "./chopsticks-test"; @@ -22,16 +23,15 @@ async function main(): Promise { // .github/workflows/xcm-tests.yml // reminder: parachains get ports in oder of arguments, starting with 8000 and incremented for each following one; // relaychain gets its port last after all parachains. - interlay: { adapter: new InterlayAdapter(), endpoints: ['ws://127.0.0.1:8000'] }, - statemint: { adapter: new StatemintAdapter(), endpoints: ['ws://127.0.0.1:8001'] }, - hydra: { adapter: new HydraAdapter(), endpoints: ['ws://127.0.0.1:8002'] }, - acala: { adapter: new AcalaAdapter(), endpoints: ['ws://127.0.0.1:8003'] }, + interlay: { adapter: new InterlayAdapter(), endpoints: ['ws://127.0.0.1:8000'] }, + statemint: { adapter: new StatemintAdapter(), endpoints: ['ws://127.0.0.1:8001'] }, + hydra: { adapter: new HydraAdapter(), endpoints: ['ws://127.0.0.1:8002'] }, + acala: { adapter: new AcalaAdapter(), endpoints: ['ws://127.0.0.1:8003'] }, // disable astar - rpc currently is too fragile for use in recurring tests // astar: { adapter: new AstarAdapter(), endpoints: ['ws://127.0.0.1:8004'] }, - // parallel: { adapter: new ParallelAdapter(), endpoints: ['ws://127.0.0.1:8005'] }, - // polkadot: { adapter: new PolkadotAdapter(), endpoints: ['ws://127.0.0.1:8006'] }, - parallel: { adapter: new ParallelAdapter(), endpoints: ['ws://127.0.0.1:8004'] }, - polkadot: { adapter: new PolkadotAdapter(), endpoints: ['ws://127.0.0.1:8005'] }, + parallel: { adapter: new ParallelAdapter(), endpoints: ['ws://127.0.0.1:8004'] }, + bifrost_polkadot: { adapter: new BifrostPolkadotAdapter(), endpoints: ['ws://127.0.0.1:8005']}, + polkadot: { adapter: new PolkadotAdapter(), endpoints: ['ws://127.0.0.1:8006'] }, }; const filterCases: Partial[] = [ diff --git a/scripts/kintsugi-chopsticks-test.ts b/scripts/kintsugi-chopsticks-test.ts index 615a2f5c..3b2f3e07 100644 --- a/scripts/kintsugi-chopsticks-test.ts +++ b/scripts/kintsugi-chopsticks-test.ts @@ -2,7 +2,7 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ /* tslint:disable:no-unused-variable */ import { KaruraAdapter } from "../src/adapters/acala"; -import { BifrostAdapter } from "../src/adapters/bifrost"; +import { BifrostKusamaAdapter } from "../src/adapters/bifrost"; import { KintsugiAdapter } from "../src/adapters/interlay"; import { HeikoAdapter } from "../src/adapters/parallel"; import { KusamaAdapter } from "../src/adapters/polkadot"; @@ -26,7 +26,7 @@ async function main(): Promise { statemine: { adapter: new StatemineAdapter(), endpoints: ['ws://127.0.0.1:8001'] }, karura: { adapter: new KaruraAdapter(), endpoints: ['ws://127.0.0.1:8002'] }, heiko: { adapter: new HeikoAdapter(), endpoints: ['ws://127.0.0.1:8003'] }, - bifrost: { adapter: new BifrostAdapter(), endpoints: ['ws://127.0.0.1:8004'] }, + bifrost: { adapter: new BifrostKusamaAdapter(), endpoints: ['ws://127.0.0.1:8004'] }, kusama: { adapter: new KusamaAdapter(), endpoints: ['ws://127.0.0.1:8005'] }, }; diff --git a/src/adapters/bifrost.ts b/src/adapters/bifrost.ts index 03267f17..8d2f5cd7 100644 --- a/src/adapters/bifrost.ts +++ b/src/adapters/bifrost.ts @@ -19,7 +19,10 @@ import { xTokensHelper } from "../utils/xtokens-helper"; const DEST_WEIGHT = "Unlimited"; -export const bifrostRoutersConfig: Omit[] = [ +export const bifrostKusamaRoutersConfig: Omit< + CrossChainRouterConfigs, + "from" +>[] = [ { to: "kintsugi", token: "VKSM", @@ -31,14 +34,43 @@ export const bifrostRoutersConfig: Omit[] = [ }, ]; -export const bifrostTokensConfig: Record = { +export const bifrostPolkadotRoutersConfig: Omit< + CrossChainRouterConfigs, + "from" +>[] = [ + { + to: "interlay", + token: "VDOT", + xcm: { + // taken from transaction: fees were 18_012_501. Add 10x margin + fee: { token: "VDOT", amount: "180125010" }, + weightLimit: DEST_WEIGHT, + }, + }, +]; + +export const bifrostKusamaTokensConfig: Record = { VKSM: { name: "VKSM", symbol: "VKSM", decimals: 12, ed: "100000000" }, }; -const SUPPORTED_TOKENS: Record = { +export const bifrostPolkadotTokensConfig: Record = { + VDOT: { name: "VDOT", symbol: "VDOT", decimals: 10, ed: "1000000" }, +}; + +const SUPPORTED_KUSAMA_TOKENS: Record = { VKSM: { VToken: "KSM" }, }; +const SUPPORTED_POLKADOT_TOKENS: Record = { + VDOT: { VToken2: 0 }, +}; + +const getSupportedTokens = (chainname: string): Record => { + return chainname === "bifrost_polkadot" + ? SUPPORTED_POLKADOT_TOKENS + : SUPPORTED_KUSAMA_TOKENS; +}; + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types const createBalanceStorages = (api: AnyApi) => { return { @@ -85,7 +117,7 @@ class BifrostBalanceAdapter extends BalanceAdapter { ); } - const tokenId = SUPPORTED_TOKENS[token]; + const tokenId = getSupportedTokens(this.chain)[token]; if (tokenId === undefined) { throw new CurrencyNotFound(token); @@ -117,10 +149,15 @@ class BaseBifrostAdapter extends BaseCrossChainAdapter { await api.isReady; + const tokensConfig = + this.chain.id === "bifrost_polkadot" + ? bifrostPolkadotTokensConfig + : bifrostKusamaTokensConfig; + this.balanceAdapter = new BifrostBalanceAdapter({ chain: this.chain.id as ChainName, api, - tokens: bifrostTokensConfig, + tokens: tokensConfig, }); } @@ -188,7 +225,7 @@ class BaseBifrostAdapter extends BaseCrossChainAdapter { const accountId = this.api.createType("AccountId32", address).toHex(); - const tokenId = SUPPORTED_TOKENS[token]; + const tokenId = getSupportedTokens(this.chain.id)[token]; if (tokenId === undefined) { throw new CurrencyNotFound(token); @@ -207,8 +244,22 @@ class BaseBifrostAdapter extends BaseCrossChainAdapter { } } -export class BifrostAdapter extends BaseBifrostAdapter { +export class BifrostKusamaAdapter extends BaseBifrostAdapter { constructor() { - super(chains.bifrost, bifrostRoutersConfig, bifrostTokensConfig); + super( + chains.bifrost, + bifrostKusamaRoutersConfig, + bifrostKusamaTokensConfig + ); + } +} + +export class BifrostPolkadotAdapter extends BaseBifrostAdapter { + constructor() { + super( + chains.bifrost_polkadot, + bifrostPolkadotRoutersConfig, + bifrostPolkadotTokensConfig + ); } } diff --git a/src/adapters/interlay.spec.ts b/src/adapters/interlay.spec.ts index 71145c93..e0eaf2e5 100644 --- a/src/adapters/interlay.spec.ts +++ b/src/adapters/interlay.spec.ts @@ -9,7 +9,7 @@ import { StatemineAdapter, StatemintAdapter } from "./statemint"; import { AcalaAdapter, KaruraAdapter } from "./acala"; import { HeikoAdapter, ParallelAdapter } from "./parallel"; import { buildTestTxWithConfigData } from "../utils/shared-spec-methods"; -import { BifrostAdapter } from "./bifrost"; +import { BifrostKusamaAdapter } from "./bifrost"; import { HydraAdapter } from "./hydradx"; import { AstarAdapter } from "./astar"; @@ -79,7 +79,7 @@ describe.skip("interlay-adapter should work", () => { const kintsugi = new KintsugiAdapter(); const karura = new KaruraAdapter(); const heiko = new HeikoAdapter(); - const bifrost = new BifrostAdapter(); + const bifrost = new BifrostKusamaAdapter(); const statemine = new StatemineAdapter(); const kusama = new KusamaAdapter(); diff --git a/src/adapters/interlay.ts b/src/adapters/interlay.ts index 652c6102..0227591b 100644 --- a/src/adapters/interlay.ts +++ b/src/adapters/interlay.ts @@ -97,6 +97,15 @@ export const interlayRoutersConfig: Omit[] = [ weightLimit: DEST_WEIGHT, }, }, + { + to: "bifrost_polkadot", + token: "VDOT", + xcm: { + // from actual transaction: fee = 703. Add 10x margin + fee: { token: "VDOT", amount: "7030" }, + weightLimit: DEST_WEIGHT, + }, + }, ]; export const kintsugiRoutersConfig: Omit[] = [ @@ -182,6 +191,7 @@ export const interlayTokensConfig: Record< IBTC: { name: "IBTC", symbol: "IBTC", decimals: 8, ed: "0" }, INTR: { name: "INTR", symbol: "INTR", decimals: 10, ed: "0" }, USDT: { name: "USDT", symbol: "USDT", decimals: 6, ed: "0" }, + VDOT: { name: "VDOT", symbol: "VDOT", decimals: 10, ed: "0" }, }, kintsugi: { KBTC: { name: "KBTC", symbol: "KBTC", decimals: 8, ed: "0" }, @@ -207,6 +217,7 @@ const INTERLAY_SUPPORTED_TOKENS: Record = { IBTC: { Token: "IBTC" }, INTR: { Token: "INTR" }, USDT: { ForeignAsset: 2 }, + VDOT: { ForeignAsset: 3 }, }; const getSupportedTokens = (chainname: string): Record => { diff --git a/src/api-provider.ts b/src/api-provider.ts index eb6c446f..4e9ee7a2 100644 --- a/src/api-provider.ts +++ b/src/api-provider.ts @@ -52,6 +52,16 @@ export class ApiProvider { prodParasPolkadotCommon.find((e) => e.info === "PolkadotAssetHub") ?.providers || {} ).filter((e) => e.startsWith("wss://")); + } else if (chain === "bifrost_polkadot" || chain === "bifrost") { + const chainInfoName = "bifrost"; + const haystack = + chain === "bifrost_polkadot" + ? prodParasPolkadot + : prodParasKusama; + + nodes = Object.values( + haystack.find((e) => e.info === chainInfoName)?.providers || {} + ).filter((e) => e.startsWith("wss://")); } else { const chainInfo = chain === "hydra" ? "hydradx" : chain; nodes = Object.values( diff --git a/src/bridge.spec.ts b/src/bridge.spec.ts index 4c2726ea..5e957385 100644 --- a/src/bridge.spec.ts +++ b/src/bridge.spec.ts @@ -10,7 +10,7 @@ import { KusamaAdapter, PolkadotAdapter } from "./adapters/polkadot"; import { StatemineAdapter, StatemintAdapter } from "./adapters/statemint"; import { HeikoAdapter, ParallelAdapter } from "./adapters/parallel"; import { AcalaAdapter, KaruraAdapter } from "./adapters/acala"; -import { BifrostAdapter } from "./adapters/bifrost"; +import { BifrostKusamaAdapter, BifrostPolkadotAdapter } from "./adapters/bifrost"; import { HydraAdapter } from "./adapters/hydradx"; import { AstarAdapter } from "./adapters/astar"; @@ -29,7 +29,8 @@ describe.skip("Bridge sdk usage", () => { statemint: new StatemintAdapter(), statemine: new StatemineAdapter(), heiko: new HeikoAdapter(), - bifrost: new BifrostAdapter(), + bifrost_polkadot: new BifrostPolkadotAdapter(), + bifrost: new BifrostKusamaAdapter(), hydra: new HydraAdapter(), parallel: new ParallelAdapter(), astar: new AstarAdapter(), @@ -178,7 +179,7 @@ describe.skip("Bridge sdk usage", () => { // printBidirectionalTxs("kintsugi", "karura", "KBTC"); // printBidirectionalTxs("kintsugi", "karura", "LKSM"); // printBidirectionalTxs("kintsugi", "bifrost", "VKSM"); - printBidirectionalTxs("kusama", "statemine", "KSM"); + // printBidirectionalTxs("kusama", "statemine", "KSM"); // interlay // printBidirectionalTxs("interlay", "polkadot", "DOT"); @@ -191,7 +192,8 @@ describe.skip("Bridge sdk usage", () => { // printBidirectionalTxs("interlay", "parallel", "IBTC"); // printBidirectionalTxs("interlay", "astar", "INTR"); // printBidirectionalTxs("interlay", "astar", "IBTC"); - printBidirectionalTxs("polkadot", "statemint", "DOT"); + printBidirectionalTxs("interlay", "bifrost_polkadot", "VDOT"); + // printBidirectionalTxs("polkadot", "statemint", "DOT"); }); test("5. getNativeToken should work", () => { @@ -209,6 +211,7 @@ describe.skip("Bridge sdk usage", () => { ["acala", "ACA"], ["hydra", "HDX"], ["parallel", "PARA"], + ["bifrost_polkadot", "BNC"], ["statemint", "DOT"], ]; diff --git a/src/configs/chains/polkadot-chains.ts b/src/configs/chains/polkadot-chains.ts index 61efbe0e..36447747 100644 --- a/src/configs/chains/polkadot-chains.ts +++ b/src/configs/chains/polkadot-chains.ts @@ -53,6 +53,14 @@ export const polkadotChains = { paraChainId: 2006, ss58Prefix: 5, }, + bifrost_polkadot: { + id: "bifrost_polkadot", + display: "Bifrost", + type: typeSubstrate, + icon: "https://resources.acala.network/_next/image?url=%2Fnetworks%2Fbifrost.png&w=96&q=75", + paraChainId: 2030, + ss58Prefix: 6, + }, interlay: { id: "interlay", display: "Interlay",