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: support system to bridge txs #383

Merged
merged 36 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c200fb6
test bridge tx interface
marshacb Mar 7, 2024
66d5ca8
add system to bridge direction
marshacb Mar 14, 2024
7dfb859
update rococo bridge tx example
marshacb Mar 14, 2024
fc38d48
remove unused const
marshacb Mar 14, 2024
b10f6bc
update resolveMultilocation to account for XCM V4 X1 junction asset l…
marshacb Mar 19, 2024
c288c8a
revert polkadot local transfer example changes
marshacb Mar 19, 2024
56d8495
update dest address in rococo bridge example
marshacb Mar 19, 2024
eee0347
lint
marshacb Mar 19, 2024
ca8136c
add error validation tests
marshacb Mar 19, 2024
e93abdd
lint
marshacb Mar 19, 2024
fd3429f
test teleports
marshacb Apr 1, 2024
5cb9fc0
update assethub metadata
marshacb May 7, 2024
d437df2
add tests for transferAssetsUsingTypeAndThen
marshacb May 10, 2024
0b69a73
update example text
marshacb May 10, 2024
16758d8
revert fetchCallType naming
marshacb May 10, 2024
69d9e9d
lint
marshacb May 10, 2024
961ad43
update default xcm on dest to account for assets length
marshacb May 10, 2024
d067eff
update examples
marshacb May 15, 2024
cda636e
add tests for checkSystemToBridgeInputs
marshacb May 15, 2024
95489ee
update system to bridge integration tests
marshacb May 15, 2024
2f15edc
update chainDestIsBridge check
marshacb May 15, 2024
6582115
add interior check to chainDestIsBridge
marshacb May 15, 2024
b08e7a5
update README
marshacb May 15, 2024
63d0931
update global consensus destination location creation
marshacb May 15, 2024
16efb17
update assetHubROCToWestend example to create transferAssets call
marshacb May 15, 2024
6b1b9a3
update assetHubROCToWestend example
marshacb May 15, 2024
20b59e1
update assetHubROCToWestend example to use LocalReserve as the assetT…
marshacb May 15, 2024
dc75c00
lint
marshacb May 15, 2024
8e53456
update example
marshacb May 16, 2024
e35390f
fix bug where toLocalLowerCase was used instead of toLowerCase
marshacb May 16, 2024
171d0e1
update spacing of system to parachain support chart
marshacb May 16, 2024
c3d66b6
add examples sending a global consensus foreign asset back to its nat…
marshacb May 16, 2024
cd2785d
update wnd to westend example
marshacb May 16, 2024
092c18a
add check to ensure polkadotXcm and xcmPallet transfers are limited t…
marshacb May 17, 2024
95d38a4
update checkXcmInputs checkAssetIdsLengthIsValid tests
marshacb May 17, 2024
a4dd286
removed foreign asset to bridgehub example
marshacb May 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* When importing from @substrate/asset-transfer-api it would look like the following
*
* import { AssetTransferApi, constructApiPromise } from '@substrate/asset-transfer-api'
*/
import { AssetTransferApi, constructApiPromise } from '../../../../../src';
import { TxResult } from '../../../../../src/types';
import { GREEN, PURPLE, RESET } from '../../../../colors';

/**
* In this example we are creating a `polkadotXcm` pallet `transferAssets` call to send WETH (foreign asset with location `{"parents":"2","interior":{"X2":[{"GlobalConsensus":{"Ethereum":{"chainId":"11155111"}}},{"AccountKey20":{"network":null,"key":"0xfff9976782d46cc05630d1f6ebab18b2324d6b14"}}]}}`)
* from a Rococo Asset Hub (System Parachain) account
* to a Rococo Bridge Hub (System ParaChain) account, where the `xcmVersion` is set to 4, the `isLimited` option is set to true and there is no
* `weightLimit` option provided which declares that the tx will allow unlimited weight to be used for fees.
*
* NOTE: When `isLimited` is true it will use the `limited` version of either `reserveTransferAssets`, or `teleportAssets`.
*/
const main = async () => {
const { api, specName, chainName, safeXcmVersion } = await constructApiPromise(
'wss://rococo-asset-hub-rpc.polkadot.io',
);
const assetApi = new AssetTransferApi(api, specName, safeXcmVersion, {
chainName,
});

let callInfo: TxResult<'call'>;
try {
callInfo = await assetApi.createTransferTransaction(
`{"parents":"2","interior":{"X1":{"GlobalConsensus":{"Ethereum":{"chainId":"11155111"}}}}}`,
'0x6E733286C3Dc52C67b8DAdFDd634eD9c3Fb05B5B',
[
`{"parents":"2","interior":{"X2":[{"GlobalConsensus":{"Ethereum":{"chainId":"11155111"}}},{"AccountKey20":{"network":null,"key":"0xfff9976782d46cc05630d1f6ebab18b2324d6b14"}}]}}`,
],
['1000000000000'],
{
format: 'call',
xcmVersion: 4,
isLimited: true,
},
);

console.log(callInfo);
} catch (e) {
console.error(e);
throw Error(e as string);
}

const decoded = assetApi.decodeExtrinsic(callInfo.tx, 'call');
console.log(`\n${PURPLE}The following decoded tx:\n${GREEN} ${JSON.stringify(JSON.parse(decoded), null, 4)}${RESET}`);
};

main()
.catch((err) => console.error(err))
.finally(() => process.exit());
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* When importing from @substrate/asset-transfer-api it would look like the following
*
* import { AssetTransferApi, constructApiPromise } from '@substrate/asset-transfer-api'
*/
import { AssetTransferApi, constructApiPromise } from '../../../../../src';
import { TxResult } from '../../../../../src/types';
import { GREEN, PURPLE, RESET } from '../../../../colors';

/**
* In this example we are creating a `foreignAssets` pallet `transfer` call to send WETH (foreign asset with location `{"parents":"2","interior":{"X2":[{"GlobalConsensus":{"Ethereum":{"chainId":"11155111"}}},{"AccountKey20":{"network":null,"key":"0xfff9976782d46cc05630d1f6ebab18b2324d6b14"}}]}}`,
`)
* from a Rococo Asset Hub (System Parachain) account
* to a Rococo Asset Hub (System Parachain) account.
*
* NOTE: When `isLimited` is true it will use the `limited` version of the either `reserveAssetTransfer`, or `teleportAssets`.
*/
const main = async () => {
const { api, specName, safeXcmVersion } = await constructApiPromise('wss://rococo-asset-hub-rpc.polkadot.io');
const assetApi = new AssetTransferApi(api, specName, safeXcmVersion);

let callInfo: TxResult<'call'>;
try {
callInfo = await assetApi.createTransferTransaction(
'1000', // NOTE: The destination id is `1000` and matches the origin chain making this a local transfer
'5EWNeodpcQ6iYibJ3jmWVe85nsok1EDG8Kk3aFg8ZzpfY1qX',
[
`{"parents":"2","interior":{"X2":[{"GlobalConsensus":{"Ethereum":{"chainId":"11155111"}}},{"AccountKey20":{"network":null,"key":"0xfff9976782d46cc05630d1f6ebab18b2324d6b14"}}]}}`,
],
['1000000000000'],
{
format: 'call',
xcmVersion: 3,
},
);

console.log(callInfo);
} catch (e) {
console.error(e);
throw Error(e as string);
}

const decoded = assetApi.decodeExtrinsic(callInfo.tx, 'call');
console.log(`\n${PURPLE}The following decoded tx:\n${GREEN} ${JSON.stringify(JSON.parse(decoded), null, 4)}${RESET}`);
};

main()
.catch((err) => console.error(err))
.finally(() => process.exit());
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* When importing from @substrate/asset-transfer-api it would look like the following
*
* import { AssetTransferApi, constructApiPromise } from '@substrate/asset-transfer-api'
*/
import { AssetTransferApi, constructApiPromise } from '../../../../../src';
import { TxResult } from '../../../../../src/types';
import { GREEN, PURPLE, RESET } from '../../../../colors';

/**
* In this example we are creating a `polkadotXcm` pallet `transferAssets` call to send WETH (foreign asset with location `{"parents":"2","interior":{"X2":[{"GlobalConsensus":{"Ethereum":{"chainId":"11155111"}}},{"AccountKey20":{"network":null,"key":"0xfff9976782d46cc05630d1f6ebab18b2324d6b14"}}]}}`)
* from a Rococo Asset Hub (System Parachain) account
* to a Rococo Contracts (System ParaChain) account, where the `xcmVersion` is set to 4, the `isLimited` option is set to true and there is no
* `weightLimit` option provided which declares that the tx will allow unlimited weight to be used for fees.
*
* NOTE: When `isLimited` is true it will use the `limited` version of either `reserveTransferAssets`, or `teleportAssets`.
*/
const main = async () => {
const { api, specName, chainName, safeXcmVersion } = await constructApiPromise(
'wss://rococo-asset-hub-rpc.polkadot.io',
);
const assetApi = new AssetTransferApi(api, specName, safeXcmVersion, {
chainName,
});

let callInfo: TxResult<'call'>;
try {
callInfo = await assetApi.createTransferTransaction(
'1002',
'5EWNeodpcQ6iYibJ3jmWVe85nsok1EDG8Kk3aFg8ZzpfY1qX',
[
`{"parents":"2","interior":{"X2":[{"GlobalConsensus":{"Ethereum":{"chainId":"11155111"}}},{"AccountKey20":{"network":null,"key":"0xfff9976782d46cc05630d1f6ebab18b2324d6b14"}}]}}`,
],
['1000000000000'],
{
format: 'call',
xcmVersion: 4,
isLimited: true,
},
);

console.log(callInfo);
} catch (e) {
console.error(e);
throw Error(e as string);
}

const decoded = assetApi.decodeExtrinsic(callInfo.tx, 'call');
console.log(`\n${PURPLE}The following decoded tx:\n${GREEN} ${JSON.stringify(JSON.parse(decoded), null, 4)}${RESET}`);
};

main()
.catch((err) => console.error(err))
.finally(() => process.exit());
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* When importing from @substrate/asset-transfer-api it would look like the following
*
* import { AssetTransferApi, constructApiPromise } from '@substrate/asset-transfer-api'
*/
import { AssetTransferApi, constructApiPromise } from '../../../../../src';
import { TxResult } from '../../../../../src/types';
import { GREEN, PURPLE, RESET } from '../../../../colors';

/**
* In this example we are creating a `polkadotXcm` pallet `transferAssets` call to send ETH (foreign asset with location `{"parents":"2","interior":{"X2":[{"GlobalConsensus":{"Ethereum":{"chainId":"11155111"}}},{"AccountKey20":{"network":null,"key":"0xfff9976782d46cc05630d1f6ebab18b2324d6b14"}}]}}`)
* from a Rococo Asset Hub (System Parachain) account
* to a Rhala Testnet (ParaChain) account, where the `xcmVersion` is set to 4, the `isLimited` option is set to true and there is no
* `weightLimit` option provided which declares that the tx will allow unlimited weight to be used for fees.
*
* NOTE: When `isLimited` is true it will use the `limited` version of either `reserveTransferAssets`, or `teleportAssets`.
*/
const main = async () => {
const { api, specName, safeXcmVersion } = await constructApiPromise('wss://rococo-asset-hub-rpc.polkadot.io');
const assetApi = new AssetTransferApi(api, specName, safeXcmVersion);

let callInfo: TxResult<'call'>;
try {
callInfo = await assetApi.createTransferTransaction(
'2004',
'5EWNeodpcQ6iYibJ3jmWVe85nsok1EDG8Kk3aFg8ZzpfY1qX',
[
`{"parents":"2","interior":{"X2":[{"GlobalConsensus":{"Ethereum":{"chainId":"11155111"}}},{"AccountKey20":{"network":null,"key":"0xfff9976782d46cc05630d1f6ebab18b2324d6b14"}}]}}`,
],
['1000000000000'],
{
format: 'call',
xcmVersion: 4,
isLimited: true,
},
);

console.log(callInfo);
} catch (e) {
console.error(e);
throw Error(e as string);
}

const decoded = assetApi.decodeExtrinsic(callInfo.tx, 'call');
console.log(`\n${PURPLE}The following decoded tx:\n${GREEN} ${JSON.stringify(JSON.parse(decoded), null, 4)}${RESET}`);
};

main()
.catch((err) => console.error(err))
.finally(() => process.exit());
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// [{"parents":"1","interior":{"X1":{"Parachain":"1,836"}}}]
/**
* When importing from @substrate/asset-transfer-api it would look like the following
*
* import { AssetTransferApi, constructApiPromise } from '@substrate/asset-transfer-api'
*/
import { AssetTransferApi, constructApiPromise } from '../../../../../src';
import { TxResult } from '../../../../../src/types';
import { GREEN, PURPLE, RESET } from '../../../../colors';

/**
* In this example we are creating a `polkadotXcm` pallet `transferAssets` call to send HOP (foreign asset with location `{"parents":"1","interior":{"X1":{"Parachain":"1,836"}}}`)
* from a Rococo Asset Hub (System Parachain) account
* to a Rhala Testnet (ParaChain) account, where the `xcmVersion` is set to 4, the `isLimited` option is set to true and there is no
* `weightLimit` option provided which declares that the tx will allow unlimited weight to be used for fees.
*
* NOTE: When `isLimited` is true it will use the `limited` version of the either `reserveAssetTransfer`, or `teleportAssets`.
*/
const main = async () => {
const { api, specName, safeXcmVersion } = await constructApiPromise('wss://rococo-asset-hub-rpc.polkadot.io');
const assetApi = new AssetTransferApi(api, specName, safeXcmVersion);

let callInfo: TxResult<'call'>;
try {
callInfo = await assetApi.createTransferTransaction(
'2004', // Note: Parachain ID 1836 (Equilibrium) is identical to the asset location's `Parachain` Id, making this a `teleportAssets` call
'5EWNeodpcQ6iYibJ3jmWVe85nsok1EDG8Kk3aFg8ZzpfY1qX',
['{"parents":"1","interior":{"X1":{"Parachain":"1836"}}}'],
['1000000000000'],
{
format: 'call',
isLimited: true,
xcmVersion: 4,
},
);

console.log(callInfo);
} catch (e) {
console.error(e);
throw Error(e as string);
}

const decoded = assetApi.decodeExtrinsic(callInfo.tx, 'call');
console.log(`\n${PURPLE}The following decoded tx:\n${GREEN} ${JSON.stringify(JSON.parse(decoded), null, 4)}${RESET}`);
};

main()
.catch((err) => console.error(err))
.finally(() => process.exit());
1 change: 1 addition & 0 deletions examples/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
],
"include": [
"./*",
"./rococo/**/*.ts",
"./kusama/**/*.ts",
"./polkadot/**/*.ts",
"../src/**/*.ts",
Expand Down
7 changes: 7 additions & 0 deletions src/AssetTransferApi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ describe('AssetTransferAPI', () => {
isDestParachain: false,
isOriginSystemParachain: true,
isOriginParachain: false,
isDestBridge: false,
};
const res = systemAssetsApi['establishDirection'](false, info);
expect(res).toEqual('SystemToSystem');
Expand All @@ -75,6 +76,7 @@ describe('AssetTransferAPI', () => {
isDestParachain: true,
isOriginSystemParachain: true,
isOriginParachain: false,
isDestBridge: false,
};
const res = systemAssetsApi['establishDirection'](false, info);
expect(res).toEqual('SystemToPara');
Expand All @@ -86,6 +88,7 @@ describe('AssetTransferAPI', () => {
isDestParachain: false,
isOriginSystemParachain: true,
isOriginParachain: false,
isDestBridge: false,
};
const res = systemAssetsApi['establishDirection'](false, info);
expect(res).toEqual('SystemToRelay');
Expand All @@ -97,6 +100,7 @@ describe('AssetTransferAPI', () => {
isDestParachain: true,
isOriginSystemParachain: false,
isOriginParachain: false,
isDestBridge: false,
};
const res = relayAssetsApi['establishDirection'](false, info);
expect(res).toEqual('RelayToPara');
Expand All @@ -108,6 +112,7 @@ describe('AssetTransferAPI', () => {
isDestParachain: false,
isOriginSystemParachain: false,
isOriginParachain: false,
isDestBridge: false,
};
const res = relayAssetsApi['establishDirection'](false, info);
expect(res).toEqual('RelayToSystem');
Expand All @@ -119,6 +124,7 @@ describe('AssetTransferAPI', () => {
isDestParachain: false,
isOriginSystemParachain: false,
isOriginParachain: true,
isDestBridge: false,
};
const res = moonriverAssetsApi['establishDirection'](false, info);
expect(res).toEqual('ParaToSystem');
Expand All @@ -130,6 +136,7 @@ describe('AssetTransferAPI', () => {
isDestParachain: true,
isOriginSystemParachain: false,
isOriginParachain: true,
isDestBridge: false,
};
const res = moonriverAssetsApi['establishDirection'](false, info);
expect(res).toEqual('ParaToPara');
Expand Down
Loading