Skip to content

Commit

Permalink
feat: support system to bridge txs (#383)
Browse files Browse the repository at this point in the history
  • Loading branch information
marshacb authored May 20, 2024
1 parent 9e272bc commit 311ecd9
Show file tree
Hide file tree
Showing 77 changed files with 3,384 additions and 218 deletions.
33 changes: 30 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,20 @@ The below chart is focusing on what directions are supported for constructing as

| Direction | V2 | V3 | V4 |
| --------------------- | ------------------ | ------------------ | ------------------ |
| System to Parachain ||||
| System to Relay ||||
| System to System ||||
| System to Bridge ||||
| System to Parachain ||||
| Relay to Parachain ||||
| Relay to System ||||
| Parachain to Parachain ||||
| Parachain to Relay ||||
| Parachain to System ||||
| System to System ||||

## Note on Parachain to Parachain Support
Parachain To Parachain support is currently limited to XCM V2, with the exception of Parachain primary asset tx construction (e.g. MOVR, SDN, etc.).

Note: System refers to System Parachains like Asset Hub.
## Note: System refers to System Parachains like Asset Hub.

## Usage

Expand Down Expand Up @@ -210,6 +211,32 @@ interface TransferArgsOpts<T extends Format> {
* Default is false.
*/
transferLiquidToken?: boolean;
/**
* The XCM `TransferType` used to transfer assets.
* Provided to construct `transferAssetsUsingTypeAndThen` transactions.
*/
assetTransferType?: string;
/**
* The RemoteReserve location for an XCM transfer.
* Should be provided when specifying an `assetTransferType` of `RemoteReserve`.
*/
remoteReserveAssetTransferTypeLocation?: string;
/**
* The XCM `TransferType` used to pay fees for an XCM transfer.
* Provided to construct `transferAssetsUsingTypeAndThen` transactions.
*/
feesTransferType?: string;
/**
* The RemoteReserve location for an XCM transfers' fees.
* Should be provided when specfying a `feesTransferType` of `RemoteReserve`.
*/
remoteReserveFeesTransferTypeLocation?: string;
/**
* Optional custom XCM message to be executed on destination chain.
* Should be provided if a custom xcm message is needed after transfering assets.
* Defaults to `Xcm(vec![DepositAsset { assets: Wild(AllCounted(assets.len())), beneficiary }])`
*/
customXcmOnDest?: string;
}
```

Expand Down
47 changes: 47 additions & 0 deletions examples/kusama/assetHub/bridgeTransfers/assetHubDOTToPolkadot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* 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 1 DOT (foreign asset with location `{"parents":"2","interior":{"X1":{"GlobalConsensus":"Polkadot"}}}`)
* from a Kusama Asset Hub (System Parachain) account
* to a Polkadot Asset Hub account, where the `xcmVersion` is set to 4 and no `weightLimit` option is provided declaring that
* the tx will allow unlimited weight to be used for fees.
*
* NOTE: To specify the amount of weight for the tx to use provide a `weightLimit` option containing desired values for `refTime` and `proofSize`.
*/
const main = async () => {
const { api, specName, safeXcmVersion } = await constructApiPromise('wss://kusama-asset-hub-rpc.polkadot.io');
const assetApi = new AssetTransferApi(api, specName, safeXcmVersion);

let callInfo: TxResult<'call'>;
try {
callInfo = await assetApi.createTransferTransaction(
`{"parents":"2","interior":{"X1":{"GlobalConsensus":"Polkadot"}}}`,
'13EoPU88424tufnjevEYbbvZ7sGV3q1uhuN4ZbUaoTsnLHYt',
[`{"parents":"2","interior":{"X1":{"GlobalConsensus":"Polkadot"}}}`],
['10000000000'],
{
format: 'call',
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());
47 changes: 47 additions & 0 deletions examples/kusama/assetHub/bridgeTransfers/assetHubKSMToPolkadot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* 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 1 KSM (asset with location `{"parents":"1","interior":{"Here":""}}`)
* from a Kusama Asset Hub (System Parachain) account
* to a Polkadot Asset Hub account, where the `xcmVersion` is set to 4 and no `weightLimit` option is provided declaring that
* the tx will allow unlimited weight to be used for fees.
*
* NOTE: To specify the amount of weight for the tx to use provide a `weightLimit` option containing desired values for `refTime` and `proofSize`.
*/
const main = async () => {
const { api, specName, safeXcmVersion } = await constructApiPromise('wss://kusama-asset-hub-rpc.polkadot.io');
const assetApi = new AssetTransferApi(api, specName, safeXcmVersion);

let callInfo: TxResult<'call'>;
try {
callInfo = await assetApi.createTransferTransaction(
`{"parents":"2","interior":{"X1":{"GlobalConsensus":"Polkadot"}}}`,
'13EoPU88424tufnjevEYbbvZ7sGV3q1uhuN4ZbUaoTsnLHYt',
[`{"parents":"1","interior":{"Here":""}}`],
['1000000000000'],
{
format: 'call',
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());
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { TxResult } from '../../../../../src/types';
import { GREEN, PURPLE, RESET } from '../../../../colors';

/**
* In this example we are creating a `polkadotXcm` pallet `limitedReserveTransferAssets` call to send MOVR (foreign asset with location `{"parents":"1","interior":{"X2":[{"Parachain":"2125"},{"GeneralIndex":"0"}]}}`)
* In this example we are creating a `polkadotXcm` pallet `transferAssets` call to send 1 MOVR (foreign asset with location `{"parents":"1","interior":{"X2":[{"Parachain":"2125"},{"GeneralIndex":"0"}]}}`)
* from a Kusama Asset Hub (System Parachain) account
* to a Bifrost (ParaChain) account, where the `xcmVersion` is set to 3 and no `weightLimit` option is provided declaring that
* the tx will allow unlimited weight to be used for fees.
Expand All @@ -25,7 +25,7 @@ const main = async () => {
'2001', // Note: Parachain ID 2001 (Bifrost) is different than the asset location's `Parachain` Id, making this a `limitedReserveTransferAssets` call
'5EWNeodpcQ6iYibJ3jmWVe85nsok1EDG8Kk3aFg8ZzpfY1qX',
['{"parents":"1","interior":{"X2":[{"Parachain":"2023"},{"PalletInstance":"10"}]}}'],
['1000000000000'],
['1000000000000000000'],
{
format: 'call',
xcmVersion: 3,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { TxResult } from '../../../../../src/types';
import { GREEN, PURPLE, RESET } from '../../../../colors';

/**
* In this example we are creating a `polkadotXcm` pallet `limitedTeleportAssets` call to send MOVR (foreign asset with location `{"parents":"1","interior":{"X2":[{"Parachain":"2023"},{"PalletInstance":"10"}]}}`)
* In this example we are creating a `polkadotXcm` pallet `transferAssets` call to send 1 MOVR (foreign asset with location `{"parents":"1","interior":{"X2":[{"Parachain":"2023"},{"PalletInstance":"10"}]}}`)
* from a Kusama Asset Hub (System Parachain) account
* to a Moonriver (ParaChain) account, where the `xcmVersion` is set to 3 and no `weightLimit` option is provided declaring that
* the tx will allow unlimited weight to be used for fees.
Expand All @@ -25,7 +25,7 @@ const main = async () => {
'2023', // Note: Parachain ID 2023 (Moonriver) is identical to the asset location's `Parachain` Id, making this a `limitedTeleportAssets` call
'5EWNeodpcQ6iYibJ3jmWVe85nsok1EDG8Kk3aFg8ZzpfY1qX',
['{"parents":"1","interior":{"X2":[{"Parachain":"2023"},{"PalletInstance":"10"}]}}'],
['1000000000000'],
['1000000000000000000'],
{
format: 'call',
xcmVersion: 3,
Expand Down
47 changes: 47 additions & 0 deletions examples/polkadot/assetHub/bridgeTransfers/assetHubDOTToKusama.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* 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 1 DOT (asset with location `{"parents":"1","interior":{"Here":""}}`)
* from a Polkadot Asset Hub (System Parachain) account
* to a Kusama Asset Hub account, where the `xcmVersion` is set to 4 and no `weightLimit` option is provided declaring that
* the tx will allow unlimited weight to be used for fees.
*
* NOTE: To specify the amount of weight for the tx to use provide a `weightLimit` option containing desired values for `refTime` and `proofSize`.
*/
const main = async () => {
const { api, specName, safeXcmVersion } = await constructApiPromise('wss://polkadot-asset-hub-rpc.polkadot.io');
const assetApi = new AssetTransferApi(api, specName, safeXcmVersion);

let callInfo: TxResult<'call'>;
try {
callInfo = await assetApi.createTransferTransaction(
`{"parents":"2","interior":{"X1":{"GlobalConsensus":"Kusama"}}}`,
'Ep7uTCvpbpMDnbfTyzbMQTQQqZ5ACGx5nUKnxmBjB4ktmSa',
[`DOT`],
['10000000000'],
{
format: 'call',
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());
47 changes: 47 additions & 0 deletions examples/polkadot/assetHub/bridgeTransfers/assetHubKSMToKusama.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* 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 1 KSM (foreign asset with location `{"parents":"2","interior":{"X1":{"GlobalConsensus":"Kusama"}}}`)
* from a Polkadot Asset Hub (System Parachain) account
* to a Kusama Asset Hub account, where the `xcmVersion` is set to 4 and no `weightLimit` option is provided declaring that
* the tx will allow unlimited weight to be used for fees.
*
* NOTE: To specify the amount of weight for the tx to use provide a `weightLimit` option containing desired values for `refTime` and `proofSize`.
*/
const main = async () => {
const { api, specName, safeXcmVersion } = await constructApiPromise('wss://polkadot-asset-hub-rpc.polkadot.io');
const assetApi = new AssetTransferApi(api, specName, safeXcmVersion);

let callInfo: TxResult<'call'>;
try {
callInfo = await assetApi.createTransferTransaction(
`{"parents":"2","interior":{"X1":{"GlobalConsensus":"Kusama"}}}`,
'13EoPU88424tufnjevEYbbvZ7sGV3q1uhuN4ZbUaoTsnLHYt',
[`{"parents":"2","interior":{"X1":{"GlobalConsensus":"Kusama"}}}`],
['1000000000000'],
{
format: 'call',
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());
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { TxResult } from '../../../../../src/types';
import { GREEN, PURPLE, RESET } from '../../../../colors';

/**
* In this example we are creating a `foreignAssets` pallet `transfer` call to send KSM (foreign asset with location {"parents":"2","interior":{"X1":{"GlobalConsensus":"Kusama"}}}`)
* In this example we are creating a `foreignAssets` pallet `transfer` call to send 1 KSM (foreign asset with location {"parents":"2","interior":{"X1":{"GlobalConsensus":"Kusama"}}}`)
* from a Polkadot Asset Hub (System Parachain) account
* to a Polkadot Asset Hub (System Parachain) account.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { TxResult } from '../../../../../src/types';
import { GREEN, PURPLE, RESET } from '../../../../colors';

/**
* In this example we are creating a `polkadotXcm` pallet `limitedReserveTransferAssets` call to send KSM (foreign asset with location '{"parents":"1","interior":{"X1":{"GlobalConsensus":"Kusama"}}}')
* In this example we are creating a `polkadotXcm` pallet `limitedReserveTransferAssets` call to send 1 KSM (foreign asset with location '{"parents":"1","interior":{"X1":{"GlobalConsensus":"Kusama"}}}')
* from a Polkadot Asset Hub (System Parachain) account
* to a Moonbeam (ParaChain) account, where the `xcmVersion` is set to 3 and no `weightLimit` option is provided declaring that
* the tx will allow unlimited weight to be used for fees.
Expand Down
47 changes: 47 additions & 0 deletions examples/rococo/assetHub/bridgeTransfers/assetHubROCToWestend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* 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 1 ROC (asset with location `{"parents":"1","interior":{"Here":""}}`)
* from a Rococo Asset Hub (System Parachain) account
* to a Westend Asset Hub account, where the `xcmVersion` is set to 4 and no `weightLimit` option is provided declaring that
* the tx will allow unlimited weight to be used for fees.
*
* NOTE: To specify the amount of weight for the tx to use provide a `weightLimit` option containing desired values for `refTime` and `proofSize`.
*/
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(
`{"parents":"2","interior":{"X1":{"GlobalConsensus":"Westend"}}}`,
'5EWNeodpcQ6iYibJ3jmWVe85nsok1EDG8Kk3aFg8ZzpfY1qX',
[`{"parents":"1","interior":{"Here":""}}`],
['1000000000000'],
{
format: 'call',
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());
Loading

0 comments on commit 311ecd9

Please sign in to comment.