@t402/polkadot 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +139 -0
  2. package/dist/exact-direct/client/index.cjs +189 -0
  3. package/dist/exact-direct/client/index.cjs.map +1 -0
  4. package/dist/exact-direct/client/index.d.cts +39 -0
  5. package/dist/exact-direct/client/index.d.ts +39 -0
  6. package/dist/exact-direct/client/index.mjs +161 -0
  7. package/dist/exact-direct/client/index.mjs.map +1 -0
  8. package/dist/exact-direct/facilitator/index.cjs +394 -0
  9. package/dist/exact-direct/facilitator/index.cjs.map +1 -0
  10. package/dist/exact-direct/facilitator/index.d.cts +55 -0
  11. package/dist/exact-direct/facilitator/index.d.ts +55 -0
  12. package/dist/exact-direct/facilitator/index.mjs +366 -0
  13. package/dist/exact-direct/facilitator/index.mjs.map +1 -0
  14. package/dist/exact-direct/server/index.cjs +277 -0
  15. package/dist/exact-direct/server/index.cjs.map +1 -0
  16. package/dist/exact-direct/server/index.d.cts +109 -0
  17. package/dist/exact-direct/server/index.d.ts +109 -0
  18. package/dist/exact-direct/server/index.mjs +248 -0
  19. package/dist/exact-direct/server/index.mjs.map +1 -0
  20. package/dist/index.cjs +293 -0
  21. package/dist/index.cjs.map +1 -0
  22. package/dist/index.d.cts +148 -0
  23. package/dist/index.d.ts +148 -0
  24. package/dist/index.mjs +235 -0
  25. package/dist/index.mjs.map +1 -0
  26. package/dist/types-Dbjfcz2Y.d.cts +135 -0
  27. package/dist/types-Dbjfcz2Y.d.ts +135 -0
  28. package/package.json +103 -0
  29. package/src/constants.ts +87 -0
  30. package/src/exact-direct/client/index.ts +5 -0
  31. package/src/exact-direct/client/scheme.ts +117 -0
  32. package/src/exact-direct/facilitator/index.ts +4 -0
  33. package/src/exact-direct/facilitator/scheme.ts +315 -0
  34. package/src/exact-direct/server/index.ts +9 -0
  35. package/src/exact-direct/server/register.ts +57 -0
  36. package/src/exact-direct/server/scheme.ts +216 -0
  37. package/src/index.ts +84 -0
  38. package/src/tokens.ts +111 -0
  39. package/src/types.ts +151 -0
  40. package/src/utils.ts +176 -0
@@ -0,0 +1,315 @@
1
+ /**
2
+ * Polkadot Exact-Direct Facilitator Scheme
3
+ *
4
+ * Verifies that a Polkadot asset transfer was executed correctly
5
+ * by querying the Subscan indexer.
6
+ */
7
+
8
+ import type {
9
+ Network,
10
+ PaymentPayload,
11
+ PaymentRequirements,
12
+ SchemeNetworkFacilitator,
13
+ SettleResponse,
14
+ VerifyResponse,
15
+ } from "@t402/core/types";
16
+ import { POLKADOT_CAIP2_NAMESPACE, SCHEME_EXACT_DIRECT, getNetworkConfig } from "../../constants.js";
17
+ import { getDefaultToken } from "../../tokens.js";
18
+ import type {
19
+ ExactDirectPolkadotPayload,
20
+ FacilitatorPolkadotSigner,
21
+ PolkadotFacilitatorConfig,
22
+ } from "../../types.js";
23
+ import {
24
+ buildExtrinsicId,
25
+ compareAddresses,
26
+ extractAssetTransfer,
27
+ extractAssetTransferFromEvents,
28
+ isValidBlockHash,
29
+ isValidExtrinsicHash,
30
+ } from "../../utils.js";
31
+
32
+ // Default configuration
33
+ const DEFAULT_MAX_EXTRINSIC_AGE = 3600; // 1 hour
34
+ const DEFAULT_CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours in ms
35
+
36
+ /**
37
+ * Exact-direct facilitator scheme for Polkadot Asset Hub
38
+ */
39
+ export class ExactDirectPolkadotFacilitator implements SchemeNetworkFacilitator {
40
+ readonly scheme = SCHEME_EXACT_DIRECT;
41
+ readonly caipFamily = `${POLKADOT_CAIP2_NAMESPACE}:*`;
42
+
43
+ private readonly signer: FacilitatorPolkadotSigner;
44
+ private readonly config: Required<PolkadotFacilitatorConfig>;
45
+ private readonly usedExtrinsics = new Map<string, number>();
46
+
47
+ constructor(
48
+ signer: FacilitatorPolkadotSigner,
49
+ config: PolkadotFacilitatorConfig = {},
50
+ ) {
51
+ this.signer = signer;
52
+ this.config = {
53
+ maxExtrinsicAge: config.maxExtrinsicAge ?? DEFAULT_MAX_EXTRINSIC_AGE,
54
+ usedExtrinsicCacheDuration:
55
+ config.usedExtrinsicCacheDuration ?? DEFAULT_CACHE_DURATION,
56
+ };
57
+
58
+ // Start cleanup interval
59
+ this.startCleanupInterval();
60
+ }
61
+
62
+ /**
63
+ * Get extra data for payment requirements
64
+ */
65
+ getExtra(network: Network): Record<string, unknown> | undefined {
66
+ const config = getNetworkConfig(network);
67
+ if (!config) return undefined;
68
+
69
+ const token = getDefaultToken(network);
70
+ return {
71
+ assetId: token?.assetId,
72
+ assetSymbol: token?.symbol,
73
+ assetDecimals: token?.decimals,
74
+ networkName: config.name,
75
+ };
76
+ }
77
+
78
+ /**
79
+ * Get facilitator signer addresses for a network
80
+ */
81
+ getSigners(network: Network): string[] {
82
+ return this.signer.getAddresses(network);
83
+ }
84
+
85
+ /**
86
+ * Verify a payment payload
87
+ */
88
+ async verify(
89
+ payload: PaymentPayload,
90
+ requirements: PaymentRequirements,
91
+ ): Promise<VerifyResponse> {
92
+ const network = requirements.network;
93
+
94
+ // Validate scheme
95
+ if (payload.accepted.scheme !== SCHEME_EXACT_DIRECT) {
96
+ return {
97
+ isValid: false,
98
+ invalidReason: `invalid_scheme: expected ${SCHEME_EXACT_DIRECT}, got ${payload.accepted.scheme}`,
99
+ };
100
+ }
101
+
102
+ // Validate network
103
+ if (payload.accepted.network !== network) {
104
+ return {
105
+ isValid: false,
106
+ invalidReason: `network_mismatch: expected ${network}, got ${payload.accepted.network}`,
107
+ };
108
+ }
109
+
110
+ // Parse payload
111
+ const polkadotPayload = payload.payload as unknown as ExactDirectPolkadotPayload;
112
+
113
+ // Validate required fields
114
+ if (!polkadotPayload.extrinsicHash && !polkadotPayload.blockHash) {
115
+ return {
116
+ isValid: false,
117
+ invalidReason: "missing_extrinsic_identifier: need extrinsicHash or blockHash",
118
+ };
119
+ }
120
+
121
+ // Validate extrinsic hash format if provided
122
+ if (polkadotPayload.extrinsicHash && !isValidExtrinsicHash(polkadotPayload.extrinsicHash)) {
123
+ return {
124
+ isValid: false,
125
+ invalidReason: "invalid_extrinsic_hash_format",
126
+ };
127
+ }
128
+
129
+ // Validate block hash format if provided
130
+ if (polkadotPayload.blockHash && !isValidBlockHash(polkadotPayload.blockHash)) {
131
+ return {
132
+ isValid: false,
133
+ invalidReason: "invalid_block_hash_format",
134
+ };
135
+ }
136
+
137
+ if (!polkadotPayload.from) {
138
+ return {
139
+ isValid: false,
140
+ invalidReason: "missing_from_address",
141
+ };
142
+ }
143
+
144
+ // Build unique identifier for replay protection
145
+ const extrinsicId = polkadotPayload.extrinsicHash ||
146
+ buildExtrinsicId(polkadotPayload.blockHash, polkadotPayload.extrinsicIndex);
147
+
148
+ // Check for replay attack
149
+ if (this.isExtrinsicUsed(extrinsicId)) {
150
+ return {
151
+ isValid: false,
152
+ invalidReason: "extrinsic_already_used",
153
+ payer: polkadotPayload.from,
154
+ };
155
+ }
156
+
157
+ // Query extrinsic
158
+ const extrinsicResult = await this.signer.queryExtrinsic(
159
+ polkadotPayload.extrinsicHash,
160
+ polkadotPayload.blockHash,
161
+ polkadotPayload.extrinsicIndex,
162
+ );
163
+
164
+ if (!extrinsicResult) {
165
+ return {
166
+ isValid: false,
167
+ invalidReason: "extrinsic_not_found",
168
+ payer: polkadotPayload.from,
169
+ };
170
+ }
171
+
172
+ // Verify extrinsic was successful
173
+ if (!extrinsicResult.success) {
174
+ return {
175
+ isValid: false,
176
+ invalidReason: "extrinsic_failed",
177
+ payer: polkadotPayload.from,
178
+ };
179
+ }
180
+
181
+ // Check extrinsic age
182
+ if (this.config.maxExtrinsicAge > 0) {
183
+ const extrinsicTime = new Date(extrinsicResult.timestamp).getTime();
184
+ const age = (Date.now() - extrinsicTime) / 1000;
185
+ if (age > this.config.maxExtrinsicAge) {
186
+ return {
187
+ isValid: false,
188
+ invalidReason: `extrinsic_too_old: ${Math.round(age)} seconds`,
189
+ payer: polkadotPayload.from,
190
+ };
191
+ }
192
+ }
193
+
194
+ // Extract transfer details
195
+ const transfer =
196
+ extractAssetTransfer(extrinsicResult) ||
197
+ extractAssetTransferFromEvents(extrinsicResult);
198
+
199
+ if (!transfer) {
200
+ return {
201
+ isValid: false,
202
+ invalidReason: "not_asset_transfer",
203
+ payer: polkadotPayload.from,
204
+ };
205
+ }
206
+
207
+ // Verify asset ID
208
+ const expectedAssetId = (requirements.extra?.assetId as number) ?? polkadotPayload.assetId;
209
+ if (transfer.assetId !== expectedAssetId) {
210
+ return {
211
+ isValid: false,
212
+ invalidReason: `asset_mismatch: expected ${expectedAssetId}, got ${transfer.assetId}`,
213
+ payer: polkadotPayload.from,
214
+ };
215
+ }
216
+
217
+ // Verify recipient
218
+ if (!compareAddresses(transfer.to, requirements.payTo)) {
219
+ return {
220
+ isValid: false,
221
+ invalidReason: `recipient_mismatch: expected ${requirements.payTo}, got ${transfer.to}`,
222
+ payer: polkadotPayload.from,
223
+ };
224
+ }
225
+
226
+ // Verify amount
227
+ const txAmount = BigInt(transfer.amount);
228
+ const requiredAmount = BigInt(requirements.amount);
229
+ if (txAmount < requiredAmount) {
230
+ return {
231
+ isValid: false,
232
+ invalidReason: `insufficient_amount: expected ${requirements.amount}, got ${transfer.amount}`,
233
+ payer: polkadotPayload.from,
234
+ };
235
+ }
236
+
237
+ // Mark extrinsic as used
238
+ this.markExtrinsicUsed(extrinsicId);
239
+
240
+ return {
241
+ isValid: true,
242
+ payer: polkadotPayload.from,
243
+ };
244
+ }
245
+
246
+ /**
247
+ * Settle a payment (for exact-direct, the transfer is already complete)
248
+ */
249
+ async settle(
250
+ payload: PaymentPayload,
251
+ requirements: PaymentRequirements,
252
+ ): Promise<SettleResponse> {
253
+ // Verify first
254
+ const verifyResult = await this.verify(payload, requirements);
255
+
256
+ if (!verifyResult.isValid) {
257
+ return {
258
+ success: false,
259
+ errorReason: verifyResult.invalidReason || "verification_failed",
260
+ payer: verifyResult.payer,
261
+ transaction: "",
262
+ network: requirements.network,
263
+ };
264
+ }
265
+
266
+ const polkadotPayload = payload.payload as unknown as ExactDirectPolkadotPayload;
267
+
268
+ // For exact-direct, settlement is already complete
269
+ return {
270
+ success: true,
271
+ transaction: polkadotPayload.extrinsicHash ||
272
+ buildExtrinsicId(polkadotPayload.blockHash, polkadotPayload.extrinsicIndex),
273
+ network: requirements.network,
274
+ payer: verifyResult.payer,
275
+ };
276
+ }
277
+
278
+ /**
279
+ * Check if an extrinsic has been used
280
+ */
281
+ private isExtrinsicUsed(extrinsicId: string): boolean {
282
+ return this.usedExtrinsics.has(extrinsicId);
283
+ }
284
+
285
+ /**
286
+ * Mark an extrinsic as used
287
+ */
288
+ private markExtrinsicUsed(extrinsicId: string): void {
289
+ this.usedExtrinsics.set(extrinsicId, Date.now());
290
+ }
291
+
292
+ /**
293
+ * Start the cleanup interval for used extrinsics cache
294
+ */
295
+ private startCleanupInterval(): void {
296
+ setInterval(() => {
297
+ const cutoff = Date.now() - this.config.usedExtrinsicCacheDuration;
298
+ for (const [extrinsicId, timestamp] of this.usedExtrinsics) {
299
+ if (timestamp < cutoff) {
300
+ this.usedExtrinsics.delete(extrinsicId);
301
+ }
302
+ }
303
+ }, 60 * 60 * 1000); // Run every hour
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Create an exact-direct facilitator for Polkadot
309
+ */
310
+ export function createExactDirectPolkadotFacilitator(
311
+ signer: FacilitatorPolkadotSigner,
312
+ config: PolkadotFacilitatorConfig = {},
313
+ ): ExactDirectPolkadotFacilitator {
314
+ return new ExactDirectPolkadotFacilitator(signer, config);
315
+ }
@@ -0,0 +1,9 @@
1
+ export {
2
+ ExactDirectPolkadotServer,
3
+ createExactDirectPolkadotServer,
4
+ } from "./scheme.js";
5
+
6
+ export {
7
+ registerExactDirectPolkadotServer,
8
+ type PolkadotServerRegistrationConfig,
9
+ } from "./register.js";
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Registration function for Polkadot exact-direct server
3
+ */
4
+
5
+ import { t402ResourceServer } from "@t402/core/server";
6
+ import type { Network } from "@t402/core/types";
7
+ import { POLKADOT_CAIP2_NAMESPACE } from "../../constants.js";
8
+ import { ExactDirectPolkadotServer, type ExactDirectPolkadotServerConfig } from "./scheme.js";
9
+
10
+ /**
11
+ * Configuration for registering Polkadot server schemes
12
+ */
13
+ export interface PolkadotServerRegistrationConfig extends ExactDirectPolkadotServerConfig {
14
+ /**
15
+ * Optional specific networks to register
16
+ * If not provided, registers wildcard support (polkadot:*)
17
+ */
18
+ networks?: Network[];
19
+ }
20
+
21
+ /**
22
+ * Registers Polkadot exact-direct payment scheme to a t402ResourceServer instance.
23
+ *
24
+ * @param server - The t402ResourceServer instance to register schemes to
25
+ * @param config - Configuration for Polkadot server registration
26
+ * @returns The server instance for chaining
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * import { registerExactDirectPolkadotServer } from "@t402/polkadot/exact-direct/server";
31
+ * import { t402ResourceServer } from "@t402/core/server";
32
+ *
33
+ * const server = new t402ResourceServer();
34
+ * registerExactDirectPolkadotServer(server, {
35
+ * networks: ["polkadot:68d56f15f85d3136970ec16946040bc1"]
36
+ * });
37
+ * ```
38
+ */
39
+ export function registerExactDirectPolkadotServer(
40
+ server: t402ResourceServer,
41
+ config: PolkadotServerRegistrationConfig = {},
42
+ ): t402ResourceServer {
43
+ const scheme = new ExactDirectPolkadotServer(config);
44
+
45
+ // Register scheme
46
+ if (config.networks && config.networks.length > 0) {
47
+ // Register specific networks
48
+ config.networks.forEach((network) => {
49
+ server.register(network, scheme);
50
+ });
51
+ } else {
52
+ // Register wildcard for all Polkadot networks
53
+ server.register(`${POLKADOT_CAIP2_NAMESPACE}:*`, scheme);
54
+ }
55
+
56
+ return server;
57
+ }
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Polkadot Exact-Direct Server Scheme
3
+ *
4
+ * Handles price parsing and payment requirement enhancement for
5
+ * Polkadot Asset Hub payments using the exact-direct scheme.
6
+ */
7
+
8
+ import type {
9
+ SchemeNetworkServer,
10
+ PaymentRequirements,
11
+ Price,
12
+ AssetAmount,
13
+ Network,
14
+ MoneyParser,
15
+ } from "@t402/core/types";
16
+ import { SCHEME_EXACT_DIRECT, isPolkadotNetwork } from "../../constants.js";
17
+ import { getDefaultToken, getTokenConfig, TOKEN_REGISTRY } from "../../tokens.js";
18
+ import { parseAmount } from "../../utils.js";
19
+
20
+ /**
21
+ * Configuration for ExactDirectPolkadotServer
22
+ */
23
+ export interface ExactDirectPolkadotServerConfig {
24
+ /** Preferred token symbol (e.g., "USDT"). Defaults to network's default token. */
25
+ preferredToken?: string;
26
+ }
27
+
28
+ /**
29
+ * Polkadot Exact-Direct Server
30
+ *
31
+ * Implements the server-side price parsing and payment requirements enhancement.
32
+ */
33
+ export class ExactDirectPolkadotServer implements SchemeNetworkServer {
34
+ readonly scheme = SCHEME_EXACT_DIRECT;
35
+ private moneyParsers: MoneyParser[] = [];
36
+ private config: ExactDirectPolkadotServerConfig;
37
+
38
+ constructor(config: ExactDirectPolkadotServerConfig = {}) {
39
+ this.config = config;
40
+ }
41
+
42
+ /**
43
+ * Register a custom money parser in the parser chain.
44
+ */
45
+ registerMoneyParser(parser: MoneyParser): ExactDirectPolkadotServer {
46
+ this.moneyParsers.push(parser);
47
+ return this;
48
+ }
49
+
50
+ /**
51
+ * Parse price into Polkadot-specific amount
52
+ */
53
+ async parsePrice(price: Price, network: Network): Promise<AssetAmount> {
54
+ // Validate network
55
+ if (!isPolkadotNetwork(network)) {
56
+ throw new Error(`Invalid Polkadot network: ${network}`);
57
+ }
58
+
59
+ // If already an AssetAmount, return it directly
60
+ if (typeof price === "object" && price !== null && "amount" in price) {
61
+ if (!price.asset) {
62
+ throw new Error(`Asset must be specified for AssetAmount on network ${network}`);
63
+ }
64
+ return {
65
+ amount: price.amount,
66
+ asset: price.asset,
67
+ extra: price.extra || {},
68
+ };
69
+ }
70
+
71
+ // Parse Money to decimal number
72
+ const amount = this.parseMoneyToDecimal(price);
73
+
74
+ // Try each custom money parser in order
75
+ for (const parser of this.moneyParsers) {
76
+ const result = await parser(amount, network);
77
+ if (result !== null) {
78
+ return result;
79
+ }
80
+ }
81
+
82
+ // All custom parsers returned null, use default conversion
83
+ return this.defaultMoneyConversion(amount, network);
84
+ }
85
+
86
+ /**
87
+ * Enhance payment requirements with Polkadot-specific details
88
+ */
89
+ async enhancePaymentRequirements(
90
+ paymentRequirements: PaymentRequirements,
91
+ supportedKind: {
92
+ t402Version: number;
93
+ scheme: string;
94
+ network: Network;
95
+ extra?: Record<string, unknown>;
96
+ },
97
+ facilitatorExtensions: string[],
98
+ ): Promise<PaymentRequirements> {
99
+ // Mark unused parameters
100
+ void facilitatorExtensions;
101
+
102
+ // Start with existing extra fields
103
+ const extra = { ...paymentRequirements.extra };
104
+
105
+ // Add any facilitator-provided extra fields
106
+ if (supportedKind.extra?.assetId) {
107
+ extra.assetId = supportedKind.extra.assetId;
108
+ }
109
+ if (supportedKind.extra?.assetSymbol) {
110
+ extra.assetSymbol = supportedKind.extra.assetSymbol;
111
+ }
112
+ if (supportedKind.extra?.assetDecimals) {
113
+ extra.assetDecimals = supportedKind.extra.assetDecimals;
114
+ }
115
+ if (supportedKind.extra?.networkName) {
116
+ extra.networkName = supportedKind.extra.networkName;
117
+ }
118
+
119
+ return {
120
+ ...paymentRequirements,
121
+ extra,
122
+ };
123
+ }
124
+
125
+ /**
126
+ * Parse Money (string | number) to a decimal number.
127
+ */
128
+ private parseMoneyToDecimal(money: string | number): number {
129
+ if (typeof money === "number") {
130
+ return money;
131
+ }
132
+
133
+ // Remove $ sign and whitespace, then parse
134
+ const cleanMoney = money.replace(/^\$/, "").trim();
135
+ const amount = parseFloat(cleanMoney);
136
+
137
+ if (isNaN(amount)) {
138
+ throw new Error(`Invalid money format: ${money}`);
139
+ }
140
+
141
+ return amount;
142
+ }
143
+
144
+ /**
145
+ * Default money conversion implementation.
146
+ */
147
+ private defaultMoneyConversion(amount: number, network: Network): AssetAmount {
148
+ const token = this.getDefaultAsset(network);
149
+
150
+ // Convert decimal amount to token amount
151
+ const tokenAmount = parseAmount(amount.toString(), token.decimals);
152
+
153
+ return {
154
+ amount: tokenAmount.toString(),
155
+ asset: this.createAssetIdentifier(network, token.assetId),
156
+ extra: {
157
+ symbol: token.symbol,
158
+ name: token.name,
159
+ decimals: token.decimals,
160
+ assetId: token.assetId,
161
+ },
162
+ };
163
+ }
164
+
165
+ /**
166
+ * Create a CAIP-19 asset identifier for Polkadot assets
167
+ */
168
+ private createAssetIdentifier(
169
+ network: Network,
170
+ assetId: number,
171
+ ): string {
172
+ return `${network}/asset:${assetId}`;
173
+ }
174
+
175
+ /**
176
+ * Get the default asset info for a network.
177
+ */
178
+ private getDefaultAsset(
179
+ network: Network,
180
+ ): { assetId: number; symbol: string; name: string; decimals: number } {
181
+ // If a preferred token is configured, try to use it
182
+ if (this.config.preferredToken) {
183
+ const preferred = getTokenConfig(network, this.config.preferredToken);
184
+ if (preferred) return preferred;
185
+ }
186
+
187
+ // Use the network's default token
188
+ const defaultToken = getDefaultToken(network);
189
+ if (defaultToken) return defaultToken;
190
+
191
+ throw new Error(`No tokens configured for network ${network}`);
192
+ }
193
+
194
+ /**
195
+ * Get all supported networks
196
+ */
197
+ static getSupportedNetworks(): string[] {
198
+ return Object.keys(TOKEN_REGISTRY);
199
+ }
200
+
201
+ /**
202
+ * Check if a network is supported
203
+ */
204
+ static isNetworkSupported(network: string): boolean {
205
+ return network in TOKEN_REGISTRY;
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Create an exact-direct server for Polkadot
211
+ */
212
+ export function createExactDirectPolkadotServer(
213
+ config: ExactDirectPolkadotServerConfig = {},
214
+ ): ExactDirectPolkadotServer {
215
+ return new ExactDirectPolkadotServer(config);
216
+ }
package/src/index.ts ADDED
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @t402/polkadot - Polkadot Asset Hub mechanism for T402
3
+ *
4
+ * This package provides support for USDT payments on Polkadot Asset Hub
5
+ * using the exact-direct scheme.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // Client usage
10
+ * import { createExactDirectPolkadotClient } from '@t402/polkadot/exact-direct/client';
11
+ *
12
+ * const client = createExactDirectPolkadotClient({
13
+ * signer: myPolkadotSigner,
14
+ * });
15
+ *
16
+ * // Server usage
17
+ * import { registerExactDirectPolkadotServer } from '@t402/polkadot/exact-direct/server';
18
+ *
19
+ * registerExactDirectPolkadotServer(server);
20
+ *
21
+ * // Facilitator usage
22
+ * import { createExactDirectPolkadotFacilitator } from '@t402/polkadot/exact-direct/facilitator';
23
+ *
24
+ * const facilitator = createExactDirectPolkadotFacilitator(signer);
25
+ * ```
26
+ */
27
+
28
+ // Re-export constants
29
+ export {
30
+ POLKADOT_CAIP2_NAMESPACE,
31
+ POLKADOT_ASSET_HUB_CAIP2,
32
+ KUSAMA_ASSET_HUB_CAIP2,
33
+ WESTEND_ASSET_HUB_CAIP2,
34
+ SCHEME_EXACT_DIRECT,
35
+ DEFAULT_POLKADOT_INDEXER,
36
+ DEFAULT_KUSAMA_INDEXER,
37
+ DEFAULT_WESTEND_INDEXER,
38
+ DEFAULT_POLKADOT_RPC,
39
+ DEFAULT_KUSAMA_RPC,
40
+ DEFAULT_WESTEND_RPC,
41
+ POLKADOT_NETWORKS,
42
+ getNetworkConfig,
43
+ isPolkadotNetwork,
44
+ type PolkadotNetworkConfig,
45
+ } from "./constants.js";
46
+
47
+ // Re-export token registry
48
+ export {
49
+ USDT_POLKADOT,
50
+ USDT_KUSAMA,
51
+ USDT_WESTEND,
52
+ TOKEN_REGISTRY,
53
+ DEFAULT_TOKENS,
54
+ getTokenConfig,
55
+ getDefaultToken,
56
+ getAssetId,
57
+ type TokenConfig,
58
+ } from "./tokens.js";
59
+
60
+ // Re-export types
61
+ export type {
62
+ ExactDirectPolkadotPayload,
63
+ PolkadotExtrinsicResult,
64
+ PolkadotEvent,
65
+ ParsedAssetTransfer,
66
+ FacilitatorPolkadotSigner,
67
+ ClientPolkadotSigner,
68
+ PolkadotServerConfig,
69
+ PolkadotFacilitatorConfig,
70
+ } from "./types.js";
71
+
72
+ // Re-export utilities
73
+ export {
74
+ isValidAddress,
75
+ isValidExtrinsicHash,
76
+ isValidBlockHash,
77
+ compareAddresses,
78
+ formatAmount,
79
+ parseAmount,
80
+ extractAssetTransfer,
81
+ extractAssetTransferFromEvents,
82
+ buildExtrinsicId,
83
+ parseExtrinsicId,
84
+ } from "./utils.js";