Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Add routes between polkadot/kusama and their asset hubs #105

Merged
merged 9 commits into from
Jul 10, 2023
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@interlay/bridge",
"version": "0.3.13",
"version": "0.3.14",
"description": "polkawallet bridge sdk",
"main": "build/index.js",
"typings": "build/index.d.ts",
Expand Down
17 changes: 17 additions & 0 deletions scripts/chopsticks-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,23 @@ export async function runTestCasesAndExit(
token: router.token
}));

// add in special cases: polkadot/kusama <=> asset hub
const relayId = chains.includes("polkadot") ? "polkadot" : "kusama";
const assetHubId = relayId === "polkadot" ? "statemint" : "statemine";
const token = relayId === "polkadot" ? "DOT" : "KSM";
testCases.push(
{
to: assetHubId as ChainName,
from: relayId as ChainName,
token
},
{
to: relayId as ChainName,
from: assetHubId as ChainName,
token
},
);

const isSkipCase = (testCase: {to: ChainName, from: ChainName, token: string}): boolean => {
return skipCases.some((skipCase) =>
(skipCase.from === undefined || testCase.from === skipCase.from) &&
Expand Down
58 changes: 54 additions & 4 deletions src/adapters/polkadot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ export const polkadotRoutersConfig: Omit<CrossChainRouterConfigs, "from">[] = [
weightLimit: "Unlimited",
},
},
{
to: "statemint",
token: "DOT",
xcm: {
// recent transfer: 1_433_579 - add 10x buffer
fee: { token: "DOT", amount: "14335790" },
weightLimit: "Unlimited",
},
},
];
export const kusamaRoutersConfig: Omit<CrossChainRouterConfigs, "from">[] = [
{
Expand All @@ -38,15 +47,21 @@ export const kusamaRoutersConfig: Omit<CrossChainRouterConfigs, "from">[] = [
weightLimit: "Unlimited",
},
},
{
to: "statemine",
token: "KSM",
xcm: {
// recent transfer: 4_778_331 - add 10x buffer
fee: { token: "KSM", amount: "47783310" },
weightLimit: "Unlimited",
},
},
];

const polkadotTokensConfig: Record<string, Record<string, BasicToken>> = {
polkadot: {
DOT: { name: "DOT", symbol: "DOT", decimals: 10, ed: "10000000000" },
},
interlay: {
DOT: { name: "DOT", symbol: "DOT", decimals: 10, ed: "10000000000" },
},
kusama: {
KSM: { name: "KSM", symbol: "KSM", decimals: 12, ed: "333333333" },
},
Expand Down Expand Up @@ -174,7 +189,42 @@ class BasePolkadotAdapter extends BaseCrossChainAdapter {

const accountId = this.api?.createType("AccountId32", address).toHex();

const [dst, acc, ass] = supportsV0V1Multilocation(this.api)
const doesSupportV0V1 = supportsV0V1Multilocation(this.api);

// to statemine
if (to === "statemine" || to === "statemint") {
const dst = {
interior: { X1: { ParaChain: toChain.paraChainId } },
parents: 0,
};
const acc = {
interior: {
X1: {
AccountId32: {
id: accountId,
network: doesSupportV0V1 ? "Any" : undefined,
},
},
},
parents: 0,
};
const ass = [
{
fun: { Fungible: amount.toChainData() },
id: { Concrete: { interior: "Here", parents: 0 } },
},
];

return this.api?.tx.xcmPallet.limitedTeleportAssets(
{ [doesSupportV0V1 ? "V1" : "V3"]: dst },
{ [doesSupportV0V1 ? "V1" : "V3"]: acc },
{ [doesSupportV0V1 ? "V1" : "V3"]: ass },
0,
"Unlimited"
);
}

const [dst, acc, ass] = doesSupportV0V1
? [
{ V0: { X1: { Parachain: toChain.paraChainId } } },
{ V0: { X1: { AccountId32: { id: accountId, network: "Any" } } } },
Expand Down
49 changes: 48 additions & 1 deletion src/adapters/statemint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ import {
import { supportsV0V1Multilocation } from "../utils/xcm-versioned-multilocation-check";

export const statemintRoutersConfig: Omit<CrossChainRouterConfigs, "from">[] = [
{
to: "polkadot",
token: "DOT",
xcm: {
// chopsticks test: 364_421_524 - use 10x buffer
fee: { token: "DOT", amount: "3644215240" },
weightLimit: "Unlimited",
},
},
{
to: "interlay",
token: "USDT",
Expand All @@ -33,6 +42,15 @@ export const statemintRoutersConfig: Omit<CrossChainRouterConfigs, "from">[] = [
];

export const statemineRoutersConfig: Omit<CrossChainRouterConfigs, "from">[] = [
{
to: "kusama",
token: "KSM",
xcm: {
// chopsticks test: 91_761_280 - use 10x buffer
fee: { token: "KSM", amount: "917612800" },
weightLimit: "Unlimited",
},
},
{
to: "kintsugi",
token: "USDT",
Expand All @@ -46,7 +64,7 @@ export const statemineTokensConfig: Record<
Record<string, BasicToken>
> = {
statemine: {
KSM: { name: "KSM", symbol: "KSM", decimals: 12, ed: "3333333" },
KSM: { name: "KSM", symbol: "KSM", decimals: 12, ed: "33333333" },
// ED set according to minBalance value of assets.asset(1984)
USDT: { name: "USDT", symbol: "USDT", decimals: 6, ed: "1000" },
},
Expand Down Expand Up @@ -237,6 +255,35 @@ class BaseStatemintAdapter extends BaseCrossChainAdapter {
throw new DestinationWeightNotFound(this.chain.id, to, token);
}

// to relay chain, support native token
if (to === "kusama" || to === "polkadot") {
if (token !== this.balanceAdapter?.nativeToken) {
throw new CurrencyNotFound(token);
}

const dst = { interior: "Here", parents: 1 };
const acc = {
interior: { X1: { AccountId32: { id: accountId } } },
parents: 0,
};
const ass = [
{
id: {
Concrete: { interior: "Here", parents: 1 },
},
fun: { Fungible: amount.toChainData() },
},
];

return this.api?.tx.polkadotXcm.limitedTeleportAssets(
{ V3: dst } as any,
{ V3: acc } as any,
{ V3: ass } as any,
0,
this.getDestWeight(token, to)?.toString() as any
);
}

const assetId = SUPPORTED_TOKENS[token];
if (
(to !== "kintsugi" && to !== "interlay") ||
Expand Down
6 changes: 4 additions & 2 deletions src/bridge.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe.skip("Bridge sdk usage", () => {
const tx = availableAdapters[fromChain].createTx({
to: toChain,
token,
amount: FN.fromInner("100000", 10),
amount: FN.fromInner("1000000000", 10),
address: testAddress,
signer: testAddress,
});
Expand Down Expand Up @@ -175,18 +175,20 @@ describe.skip("Bridge sdk usage", () => {
// printBidirectionalTxs("kintsugi", "karura", "KBTC");
// printBidirectionalTxs("kintsugi", "karura", "LKSM");
// printBidirectionalTxs("kintsugi", "bifrost", "VKSM");
printBidirectionalTxs("kusama", "statemine", "KSM");

// interlay
// printBidirectionalTxs("interlay", "polkadot", "DOT");
// printBidirectionalTxs("interlay", "statemint", "USDT");
// printBidirectionalTxs("interlay", "hydra", "IBTC");
printBidirectionalTxs("interlay", "hydra", "INTR");
// printBidirectionalTxs("interlay", "hydra", "INTR");
// printBidirectionalTxs("interlay", "acala", "INTR");
// printBidirectionalTxs("interlay", "acala", "IBTC");
// printBidirectionalTxs("interlay", "parallel", "INTR");
// printBidirectionalTxs("interlay", "parallel", "IBTC");
// printBidirectionalTxs("interlay", "astar", "INTR");
// printBidirectionalTxs("interlay", "astar", "IBTC");
printBidirectionalTxs("polkadot", "statemint", "DOT");
});

test("5. getNativeToken should work", () => {
Expand Down