Skip to content

Commit ecd221b

Browse files
committed
Add tutorial for paying transaction fees with different tokens
1 parent 2f5afde commit ecd221b

File tree

4 files changed

+257
-0
lines changed

4 files changed

+257
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<div id="termynal" data-termynal>
2+
<span data-ty="input"><span class="file-path"></span>npx ts-node fee-payment-transaction.ts</span>
3+
<pre>
4+
Tx finalized: 0x771956fdf40b3741bdc3c1e981a6daacbe5521877ad1915542e7413bb4a820bc (ok=true)
5+
Block: #9645060 0x57710514f168b5c444c8e47b1e1a31dd9e7bc7e9a51d8d25ccdbc6053e159f6b [tx index 2]
6+
Events:
7+
- Assets
8+
- Balances
9+
- Assets
10+
- AssetConversion
11+
- Balances
12+
- Balances
13+
- AssetTxPayment
14+
- System
15+
</pre>
16+
</div>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { sr25519CreateDerive } from "@polkadot-labs/hdkd";
2+
import {
3+
DEV_PHRASE,
4+
entropyToMiniSecret,
5+
mnemonicToEntropy,
6+
} from "@polkadot-labs/hdkd-helpers";
7+
import { getPolkadotSigner } from "polkadot-api/signer";
8+
import { createClient } from "polkadot-api";
9+
import { assetHub } from "@polkadot-api/descriptors";
10+
import { withPolkadotSdkCompat } from "polkadot-api/polkadot-sdk-compat";
11+
import { getWsProvider } from "polkadot-api/ws-provider/node";
12+
import { MultiAddress } from "@polkadot-api/descriptors";
13+
14+
const TARGET_ADDRESS = "14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3"; // Bob's address
15+
const TRANSFER_AMOUNT = 3_000_000_000n; // 3 DOT
16+
const USD_ASSET_ID = 1337;
17+
18+
const createSigner = async () => {
19+
const entropy = mnemonicToEntropy(DEV_PHRASE);
20+
const miniSecret = entropyToMiniSecret(entropy);
21+
const derive = sr25519CreateDerive(miniSecret);
22+
const hdkdKeyPair = derive("//Alice");
23+
const polkadotSigner = getPolkadotSigner(
24+
hdkdKeyPair.publicKey,
25+
"Sr25519",
26+
hdkdKeyPair.sign
27+
);
28+
return polkadotSigner;
29+
};
30+
31+
const client = createClient(
32+
withPolkadotSdkCompat(
33+
getWsProvider("ws://localhost:8000") // Chopsticks Asset Hub
34+
)
35+
);
36+
37+
const api = client.getTypedApi(assetHub);
38+
39+
const tx = api.tx.Balances.transfer_keep_alive({
40+
dest: MultiAddress.Id(TARGET_ADDRESS),
41+
value: BigInt(TRANSFER_AMOUNT),
42+
});
43+
44+
const signer = await createSigner();
45+
46+
const result = await tx.signAndSubmit(signer, {
47+
asset: {
48+
parents: 0,
49+
interior: {
50+
type: "X2",
51+
value: [
52+
{ type: "PalletInstance", value: 50 },
53+
{ type: "GeneralIndex", value: BigInt(USD_ASSET_ID) },
54+
],
55+
},
56+
},
57+
});
58+
59+
const { txHash, ok, block, events } = result;
60+
console.log(`Tx finalized: ${txHash} (ok=${ok})`);
61+
console.log(`Block: #${block.number} ${block.hash} [tx index ${block.index}]`);
62+
63+
console.log("Events:");
64+
for (const ev of events) {
65+
const type = (ev as any).type ?? "unknown";
66+
console.log(`- ${type}`);
67+
}
68+
69+
process.exit(0);

tutorials/interoperability/.nav.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ nav:
55
- xcm-transfers
66
- 'Replay and Dry Run XCMs': replay-and-dry-run-xcms.md
77
- 'XCM Fee Estimation': xcm-fee-estimation.md
8+
- 'Pay Transaction Fees with Different Tokens': pay-tx-with-different-fees.md
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
---
2+
title: Send Transaction Paying Fees with Different Tokens
3+
description: This tutorial demonstrates how to send a DOT transfer transaction while paying the fees using a different token on the Asset Hub.
4+
---
5+
6+
# Send Transaction Paying Fees with Different Tokens
7+
8+
## Introduction
9+
10+
The Asset Hub provides a powerful feature that allows users to pay transaction fees using alternative tokens instead of the native token of the chain.
11+
12+
This tutorial demonstrates how to send a DOT transfer transaction while paying the fees using a different token (USDT in this example) on the Asset Hub.
13+
14+
## Environment Setup
15+
16+
Let's set up the development environment for this tutorial:
17+
18+
1. Create a new directory and initialize the project:
19+
20+
```bash
21+
mkdir fee-payment-tutorial && \
22+
cd fee-payment-tutorial
23+
```
24+
25+
2. Initialize the project:
26+
27+
```bash
28+
npm init -y
29+
```
30+
31+
3. Install dev dependencies:
32+
33+
```bash
34+
npm install --save-dev @types/node@^22.12.0 ts-node@^10.9.2 typescript@^5.7.3
35+
```
36+
37+
4. Install dependencies:
38+
39+
```bash
40+
npm install --save @polkadot-labs/hdkd@^0.0.13 @polkadot-labs/hdkd-helpers@^0.0.13 [email protected]
41+
```
42+
43+
5. Create TypeScript configuration:
44+
45+
```bash
46+
npx tsc --init
47+
```
48+
49+
6. Generate the types for the Polkadot API for Asset Hub:
50+
51+
```bash
52+
npx papi add assetHub -n polkadot_asset_hub
53+
```
54+
55+
7. Create a new file called `fee-payment-transaction.ts`:
56+
57+
```bash
58+
touch fee-payment-transaction.ts
59+
```
60+
61+
## Local Asset Hub Setup
62+
63+
Before running the script, you'll need to fork the Asset Hub locally using Chopsticks:
64+
65+
```bash
66+
chopsticks -c polkadot-asset-hub
67+
```
68+
69+
This command will fork the Asset Hub chain and make it available at `ws://localhost:8000`.
70+
71+
## Implementation
72+
73+
Now let's implement the fee payment transaction step by step.
74+
75+
### Import Dependencies
76+
77+
Add the following imports to your `fee-payment-transaction.ts` file:
78+
79+
```typescript title="fee-payment-transaction.ts"
80+
--8<-- "code/tutorials/interoperability/pay-tx-with-different-fees/fee-payment-transaction.ts:1:12"
81+
```
82+
83+
### Define Constants
84+
85+
Define the constants for your transaction:
86+
87+
```typescript title="fee-payment-transaction.ts"
88+
--8<-- "code/tutorials/interoperability/pay-tx-with-different-fees/fee-payment-transaction.ts:14:16"
89+
```
90+
91+
### Create Signer
92+
93+
Create a signer using Alice's development account:
94+
95+
```typescript title="fee-payment-transaction.ts"
96+
--8<-- "code/tutorials/interoperability/pay-tx-with-different-fees/fee-payment-transaction.ts:18:29"
97+
```
98+
99+
This function will return a signer that can be used to sign the transaction.
100+
101+
### Setup Client and API
102+
103+
Create the client connection to the local Asset Hub:
104+
105+
```typescript title="fee-payment-transaction.ts"
106+
--8<-- "code/tutorials/interoperability/pay-tx-with-different-fees/fee-payment-transaction.ts:31:37"
107+
```
108+
109+
### Create the Transaction
110+
111+
Create a standard DOT transfer transaction:
112+
113+
```typescript title="fee-payment-transaction.ts"
114+
--8<-- "code/tutorials/interoperability/pay-tx-with-different-fees/fee-payment-transaction.ts:39:42"
115+
```
116+
117+
This creates a transaction that transfers 3 DOT to Bob's address while keeping Alice's account alive.
118+
119+
### Sign and Submit with Alternative Fee Payment
120+
121+
The key part of this tutorial is specifying an alternative asset for fee payment. This is done through the `asset` parameter in the `signAndSubmit` options:
122+
123+
```typescript title="fee-payment-transaction.ts"
124+
--8<-- "code/tutorials/interoperability/pay-tx-with-different-fees/fee-payment-transaction.ts:44:69"
125+
```
126+
127+
This specifies that the fees should be paid using the USDT asset.
128+
129+
## Full Code
130+
131+
The full code for the complete implementation is the following:
132+
133+
??? code "Complete Code"
134+
135+
```typescript title="fee-payment-transaction.ts"
136+
--8<-- "code/tutorials/interoperability/pay-tx-with-different-fees/fee-payment-transaction.ts"
137+
```
138+
139+
## Running the Script
140+
141+
1. Make sure Chopsticks is running with the Asset Hub fork:
142+
143+
```bash
144+
chopsticks -c polkadot-asset-hub
145+
```
146+
147+
2. Run the script:
148+
149+
```bash
150+
npx ts-node fee-payment-transaction.ts
151+
```
152+
153+
## Expected Output
154+
155+
When you run the script successfully, you should see output similar to:
156+
157+
--8<-- "code/tutorials/interoperability/pay-tx-with-different-fees/fee-payment-transaction-output.html"
158+
159+
The key events to look for are:
160+
161+
- **Assets**: The asset was transferred
162+
- **Balances**: The fees were paid using the alternative asset
163+
- **AssetConversion**: The fees were converted to the alternative asset
164+
- **AssetTxPayment**: The fees were paid using the alternative asset
165+
- **System**: The transaction was successful
166+
167+
## Conclusion
168+
169+
Paying transaction fees with alternative tokens on Asset Hub provides significant flexibility for users and applications.
170+
171+
The key takeaway is understanding how to specify alternative assets using the XCM location format, which opens up possibilities for building applications that can operate entirely using specific token ecosystems while still leveraging the full power of the network.

0 commit comments

Comments
 (0)