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

V3 next xcm payment api #354

Merged
merged 22 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 16 additions & 16 deletions examples/sdk-simple/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { dot, moonbeam, polkadot } from "@moonbeam-network/xcm-config";
import { Sdk, type TransferData } from "@moonbeam-network/xcm-sdk";
import { Keyring } from "@polkadot/api";
import { cryptoWaitReady } from "@polkadot/util-crypto";
import { http, type Address, createWalletClient } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { dot, moonbeam, polkadot } from '@moonbeam-network/xcm-config';
import { Sdk, type TransferData } from '@moonbeam-network/xcm-sdk';
import { Keyring } from '@polkadot/api';
import { cryptoWaitReady } from '@polkadot/util-crypto';
import { http, type Address, createWalletClient } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';

// Moonbeam Signer ===========================================================

const moonbeamPrivateKey = "";
const moonbeamPrivateKey = '';
const account = privateKeyToAccount(moonbeamPrivateKey as Address);
const walletClient = createWalletClient({
account,
Expand All @@ -17,12 +17,12 @@ const walletClient = createWalletClient({

// Polkadot Signer ===========================================================

const polkadotPrivateKey = "";
const polkadotPrivateKey = '';

await cryptoWaitReady();
const keyring = new Keyring({
ss58Format: polkadot.ss58Format,
type: "sr25519",
type: 'sr25519',
});
const pair = keyring.createFromUri(polkadotPrivateKey);

Expand All @@ -32,14 +32,14 @@ export function logBalances(data: TransferData): void {
console.log(
`Balance on ${data.source.chain.name} ${data.source.balance.toDecimal()} ${
data.source.balance.symbol
}`
}`,
);
console.log(
`Balance on ${
data.destination.chain.name
} ${data.destination.balance.toDecimal()} ${
data.destination.balance.symbol
}`
}`,
);
}

Expand All @@ -57,12 +57,12 @@ export function logTxDetails(data: TransferData): void {
data.source.chain.name
} and ${data.destination.fee.toDecimal()} ${
data.destination.fee.symbol
} fee on ${data.destination.chain.name}.`
} fee on ${data.destination.chain.name}.`,
);
}

export async function fromPolkadot() {
console.log("\nTransfer from Polkadot to Moonbeam\n");
console.log('\nTransfer from Polkadot to Moonbeam\n');

const data = await Sdk().getTransferData({
destinationAddress: account.address,
Expand All @@ -86,7 +86,7 @@ export async function fromPolkadot() {
}

export async function fromMoonbeam() {
console.log("\nTransfer from Moonbeam to Polkadot\n");
console.log('\nTransfer from Moonbeam to Polkadot\n');

const data = await Sdk()
.assets()
Expand Down Expand Up @@ -118,12 +118,12 @@ async function main() {
console.log(`Polkadot address: ${pair.address}.`);

await fromPolkadot();
console.log("\nWaiting 30 seconds...");
console.log('\nWaiting 30 seconds...');
await setTimeout(30000);
await fromMoonbeam();
}

main()
.then(() => console.log("done!"))
.then(() => console.log('done!'))
.catch(console.error)
.finally(() => process.exit());
4 changes: 3 additions & 1 deletion mkdocs/docs/contribute.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,9 @@ export const polkadotAssetHubConfig = new ChainConfig({
balance: BalanceBuilder().substrate().assets().account(),
destination: moonbeam,
destinationFee: {
amount: FeeBuilder().assetManager().assetTypeUnitsPerSecond(),
amount: FeeBuilder()
.xcmPaymentApi()
.xcmPaymentFee({ isAssetReserveChain: false }),
asset: usdt,
balance: BalanceBuilder().substrate().assets().account(),
},
Expand Down
12 changes: 9 additions & 3 deletions mkdocs/docs/reference/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,9 @@ Defines a chain's configurations, including information for each chain's support
balance: BalanceBuilder().substrate().assets().account(),
destination: moonbeam,
destinationFee: {
amount: FeeBuilder().assetManager().assetTypeUnitsPerSecond(),
amount: FeeBuilder()
.xcmPaymentApi()
.xcmPaymentFee({ isAssetReserveChain: false }),
asset: usdt,
balance: BalanceBuilder().substrate().assets().account(),
},
Expand Down Expand Up @@ -761,7 +763,9 @@ Defines an asset's configurations for a source chain and includes information ab
balance: BalanceBuilder().substrate().assets().account(),
destination: moonbeam,
destinationFee: {
amount: FeeBuilder().assetManager().assetTypeUnitsPerSecond(),
amount: FeeBuilder()
.xcmPaymentApi()
.xcmPaymentFee({ isAssetReserveChain: false }),
asset: usdt,
balance: BalanceBuilder().substrate().assets().account(),
},
Expand Down Expand Up @@ -831,7 +835,9 @@ Defines the fees for a particular asset on the destination chain.
{
asset: dot,
balance: BalanceBuilder().substrate().system().account(),
amount: FeeBuilder().assetManager().assetTypeUnitsPerSecond(),
amount: amount: FeeBuilder()
.xcmPaymentApi()
.xcmPaymentFee({ isAssetReserveChain: false }),
}
```

Expand Down
19 changes: 19 additions & 0 deletions packages/builder/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# @moonbeam-network/xcm-builder

## 2.5.1

### Patch Changes

- Updated dependencies [[`4be5659`](https://github.com/moonbeam-foundation/xcm-sdk/commit/4be5659c05fe2487dd6f440c833fdf7cdc369917)]:
- @moonbeam-network/[email protected]
- @moonbeam-network/[email protected]

## 2.5.0

### Minor Changes

- [#351](https://github.com/moonbeam-foundation/xcm-sdk/pull/351) [`2a7ed04`](https://github.com/moonbeam-foundation/xcm-sdk/commit/2a7ed04887ee41e5a6c010f213265028a953a769) Thanks [@mmaurello](https://github.com/mmaurello)! - Implement XcmPaymentApi to calculate fees for routes going to Moonbeam / Moonriver / Moonbase-Alpha

### Patch Changes

- Updated dependencies [[`2a7ed04`](https://github.com/moonbeam-foundation/xcm-sdk/commit/2a7ed04887ee41e5a6c010f213265028a953a769)]:
- @moonbeam-network/[email protected]

## 2.4.7

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/builder/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@moonbeam-network/xcm-builder",
"version": "2.4.7",
"version": "2.5.1",
"description": "Moonbeam XCM builder",
"scripts": {
"build": "tsup",
Expand Down
20 changes: 18 additions & 2 deletions packages/builder/src/fee/FeeBuilder.interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { ChainAssetId } from '@moonbeam-network/xcm-types';
import type { AnyParachain, ChainAsset } from '@moonbeam-network/xcm-types';
import type { ApiPromise } from '@polkadot/api';
import type { Enum } from '@polkadot/types';
import type { StagingXcmV3MultiLocation } from '@polkadot/types/lookup';
import type { ConfigBuilder } from '../builder.interfaces';
import type { SubstrateCallConfig } from '../types/substrate/SubstrateCallConfig';

Expand All @@ -9,6 +11,20 @@ export type FeeConfigBuilder = ConfigBuilder<
>;

export interface FeeConfigBuilderPrams {
asset: ChainAssetId;
address: string;
api: ApiPromise;
asset: ChainAsset;
destination: AnyParachain;
feeAsset: ChainAsset;
}

export interface XcmPaymentFeeProps {
isAssetReserveChain: boolean;
shouldTransferAssetPrecedeFeeAsset?: boolean;
}

export interface MoonbeamRuntimeXcmConfigAssetType extends Enum {
readonly isXcm: boolean;
readonly asXcm: StagingXcmV3MultiLocation;
readonly type: 'Xcm';
}
79 changes: 59 additions & 20 deletions packages/builder/src/fee/FeeBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,77 @@
import type { Option, u128 } from '@polkadot/types';
/* eslint-disable sort-keys */
/* eslint-disable @typescript-eslint/no-use-before-define */

import { SubstrateCallConfig } from '../types/substrate/SubstrateCallConfig';
import type { FeeConfigBuilder } from './FeeBuilder.interfaces';
import type {
FeeConfigBuilder,
FeeConfigBuilderPrams,
XcmPaymentFeeProps,
} from './FeeBuilder.interfaces';
import {
getBuyExecutionInstruction,
getClearOriginInstruction,
getDepositAssetInstruction,
getFeeForXcmInstructionsAndAsset,
getReserveAssetDepositedInstruction,
getSetTopicInstruction,
getVersionedAssetId,
getWithdrawAssetInstruction,
} from './FeeBuilder.utils';

export function FeeBuilder() {
return {
assetManager,
xcmPaymentApi,
};
}

function assetManager() {
function xcmPaymentApi() {
return {
assetTypeUnitsPerSecond: (weight = 1_000_000_000): FeeConfigBuilder => ({
build: ({ api, asset }) =>
xcmPaymentFee: ({
isAssetReserveChain,
shouldTransferAssetPrecedeFeeAsset = false,
}: XcmPaymentFeeProps): FeeConfigBuilder => ({
build: ({
address,
api,
asset,
destination,
feeAsset,
}: FeeConfigBuilderPrams) =>
new SubstrateCallConfig({
api,
call: async (): Promise<bigint> => {
const type = (await api.query.assetManager.assetIdType(
const versionedFeeAssetId = await getVersionedAssetId(
api,
feeAsset,
destination,
);
const versionedTransferAssetId = await getVersionedAssetId(
api,
asset,
// biome-ignore lint/suspicious/noExplicitAny: not sure how to fix this
)) as unknown as Option<any>;

if (type.isNone) {
throw new Error(`No asset type found for asset ${asset}`);
}

const unwrappedType = type.unwrap();
destination,
);
const versionedAssets = shouldTransferAssetPrecedeFeeAsset
? [versionedTransferAssetId, versionedFeeAssetId]
: [versionedFeeAssetId, versionedTransferAssetId];

const res = (await api.query.assetManager.assetTypeUnitsPerSecond(
unwrappedType,
)) as unknown as Option<u128>;
const assets =
feeAsset === asset ? [versionedFeeAssetId] : versionedAssets;

const unitsPerSecond = res.unwrapOrDefault().toBigInt();
const instructions = [
isAssetReserveChain
? getWithdrawAssetInstruction(assets)
: getReserveAssetDepositedInstruction(assets),
getClearOriginInstruction(),
getBuyExecutionInstruction(versionedFeeAssetId),
getDepositAssetInstruction(address, assets),
getSetTopicInstruction(),
];

return (BigInt(weight) * unitsPerSecond) / BigInt(10 ** 12);
return getFeeForXcmInstructionsAndAsset(
api,
instructions,
versionedFeeAssetId,
);
},
}),
}),
Expand Down
Loading
Loading