@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.
- package/README.md +139 -0
- package/dist/exact-direct/client/index.cjs +189 -0
- package/dist/exact-direct/client/index.cjs.map +1 -0
- package/dist/exact-direct/client/index.d.cts +39 -0
- package/dist/exact-direct/client/index.d.ts +39 -0
- package/dist/exact-direct/client/index.mjs +161 -0
- package/dist/exact-direct/client/index.mjs.map +1 -0
- package/dist/exact-direct/facilitator/index.cjs +394 -0
- package/dist/exact-direct/facilitator/index.cjs.map +1 -0
- package/dist/exact-direct/facilitator/index.d.cts +55 -0
- package/dist/exact-direct/facilitator/index.d.ts +55 -0
- package/dist/exact-direct/facilitator/index.mjs +366 -0
- package/dist/exact-direct/facilitator/index.mjs.map +1 -0
- package/dist/exact-direct/server/index.cjs +277 -0
- package/dist/exact-direct/server/index.cjs.map +1 -0
- package/dist/exact-direct/server/index.d.cts +109 -0
- package/dist/exact-direct/server/index.d.ts +109 -0
- package/dist/exact-direct/server/index.mjs +248 -0
- package/dist/exact-direct/server/index.mjs.map +1 -0
- package/dist/index.cjs +293 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +148 -0
- package/dist/index.d.ts +148 -0
- package/dist/index.mjs +235 -0
- package/dist/index.mjs.map +1 -0
- package/dist/types-Dbjfcz2Y.d.cts +135 -0
- package/dist/types-Dbjfcz2Y.d.ts +135 -0
- package/package.json +103 -0
- package/src/constants.ts +87 -0
- package/src/exact-direct/client/index.ts +5 -0
- package/src/exact-direct/client/scheme.ts +117 -0
- package/src/exact-direct/facilitator/index.ts +4 -0
- package/src/exact-direct/facilitator/scheme.ts +315 -0
- package/src/exact-direct/server/index.ts +9 -0
- package/src/exact-direct/server/register.ts +57 -0
- package/src/exact-direct/server/scheme.ts +216 -0
- package/src/index.ts +84 -0
- package/src/tokens.ts +111 -0
- package/src/types.ts +151 -0
- package/src/utils.ts +176 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { Network } from '@t402/core/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Polkadot Asset Hub T402 Types
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Payment payload for exact-direct scheme on Polkadot
|
|
9
|
+
*/
|
|
10
|
+
type ExactDirectPolkadotPayload = {
|
|
11
|
+
/** Extrinsic hash (block hash + extrinsic index) */
|
|
12
|
+
extrinsicHash: string;
|
|
13
|
+
/** Block hash containing the extrinsic */
|
|
14
|
+
blockHash: string;
|
|
15
|
+
/** Extrinsic index within the block */
|
|
16
|
+
extrinsicIndex: number;
|
|
17
|
+
/** Sender address (SS58 format) */
|
|
18
|
+
from: string;
|
|
19
|
+
/** Recipient address (SS58 format) */
|
|
20
|
+
to: string;
|
|
21
|
+
/** Amount in smallest unit (with decimals) */
|
|
22
|
+
amount: string;
|
|
23
|
+
/** Asset ID */
|
|
24
|
+
assetId: number;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Result of a Polkadot extrinsic query
|
|
28
|
+
*/
|
|
29
|
+
interface PolkadotExtrinsicResult {
|
|
30
|
+
/** Extrinsic hash */
|
|
31
|
+
extrinsicHash: string;
|
|
32
|
+
/** Block hash */
|
|
33
|
+
blockHash: string;
|
|
34
|
+
/** Block number */
|
|
35
|
+
blockNumber: number;
|
|
36
|
+
/** Extrinsic index */
|
|
37
|
+
extrinsicIndex: number;
|
|
38
|
+
/** Timestamp (ISO 8601) */
|
|
39
|
+
timestamp: string;
|
|
40
|
+
/** Signer address */
|
|
41
|
+
signer: string;
|
|
42
|
+
/** Success status */
|
|
43
|
+
success: boolean;
|
|
44
|
+
/** Module name (e.g., "assets") */
|
|
45
|
+
module: string;
|
|
46
|
+
/** Call name (e.g., "transfer") */
|
|
47
|
+
call: string;
|
|
48
|
+
/** Call arguments */
|
|
49
|
+
args: Record<string, unknown>;
|
|
50
|
+
/** Events emitted by the extrinsic */
|
|
51
|
+
events: PolkadotEvent[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Polkadot event structure
|
|
55
|
+
*/
|
|
56
|
+
interface PolkadotEvent {
|
|
57
|
+
/** Module name */
|
|
58
|
+
module: string;
|
|
59
|
+
/** Event name */
|
|
60
|
+
name: string;
|
|
61
|
+
/** Event data */
|
|
62
|
+
data: Record<string, unknown>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Parsed asset transfer from extrinsic
|
|
66
|
+
*/
|
|
67
|
+
interface ParsedAssetTransfer {
|
|
68
|
+
/** Asset ID */
|
|
69
|
+
assetId: number;
|
|
70
|
+
/** Sender address */
|
|
71
|
+
from: string;
|
|
72
|
+
/** Recipient address */
|
|
73
|
+
to: string;
|
|
74
|
+
/** Amount transferred */
|
|
75
|
+
amount: string;
|
|
76
|
+
/** Whether the transfer was successful */
|
|
77
|
+
success: boolean;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Signer interface for Polkadot facilitator
|
|
81
|
+
*/
|
|
82
|
+
interface FacilitatorPolkadotSigner {
|
|
83
|
+
/**
|
|
84
|
+
* Get the facilitator's addresses for a network
|
|
85
|
+
*/
|
|
86
|
+
getAddresses(network: Network): string[];
|
|
87
|
+
/**
|
|
88
|
+
* Query an extrinsic by hash
|
|
89
|
+
*/
|
|
90
|
+
queryExtrinsic(extrinsicHash: string, blockHash?: string, extrinsicIndex?: number): Promise<PolkadotExtrinsicResult | null>;
|
|
91
|
+
/**
|
|
92
|
+
* Get balance of an asset for an address
|
|
93
|
+
*/
|
|
94
|
+
getBalance(assetId: number, address: string): Promise<string>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Client signer interface for signing transactions
|
|
98
|
+
*/
|
|
99
|
+
interface ClientPolkadotSigner {
|
|
100
|
+
/**
|
|
101
|
+
* Get the signer's address
|
|
102
|
+
*/
|
|
103
|
+
getAddress(): Promise<string>;
|
|
104
|
+
/**
|
|
105
|
+
* Sign and submit an asset transfer
|
|
106
|
+
* Returns the extrinsic hash, block hash, and extrinsic index
|
|
107
|
+
*/
|
|
108
|
+
transferAsset(assetId: number, to: string, amount: string): Promise<{
|
|
109
|
+
extrinsicHash: string;
|
|
110
|
+
blockHash: string;
|
|
111
|
+
extrinsicIndex: number;
|
|
112
|
+
}>;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Configuration for Polkadot server
|
|
116
|
+
*/
|
|
117
|
+
interface PolkadotServerConfig {
|
|
118
|
+
/** Custom RPC URL */
|
|
119
|
+
rpcUrl?: string;
|
|
120
|
+
/** Custom indexer URL */
|
|
121
|
+
indexerUrl?: string;
|
|
122
|
+
/** Facilitator addresses per network */
|
|
123
|
+
facilitatorAddresses?: Record<string, string>;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Configuration for Polkadot facilitator
|
|
127
|
+
*/
|
|
128
|
+
interface PolkadotFacilitatorConfig {
|
|
129
|
+
/** Maximum age of extrinsic to accept (in seconds) */
|
|
130
|
+
maxExtrinsicAge?: number;
|
|
131
|
+
/** Duration to cache used extrinsic hashes */
|
|
132
|
+
usedExtrinsicCacheDuration?: number;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export type { ClientPolkadotSigner as C, ExactDirectPolkadotPayload as E, FacilitatorPolkadotSigner as F, PolkadotExtrinsicResult as P, ParsedAssetTransfer as a, PolkadotEvent as b, PolkadotServerConfig as c, PolkadotFacilitatorConfig as d };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { Network } from '@t402/core/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Polkadot Asset Hub T402 Types
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Payment payload for exact-direct scheme on Polkadot
|
|
9
|
+
*/
|
|
10
|
+
type ExactDirectPolkadotPayload = {
|
|
11
|
+
/** Extrinsic hash (block hash + extrinsic index) */
|
|
12
|
+
extrinsicHash: string;
|
|
13
|
+
/** Block hash containing the extrinsic */
|
|
14
|
+
blockHash: string;
|
|
15
|
+
/** Extrinsic index within the block */
|
|
16
|
+
extrinsicIndex: number;
|
|
17
|
+
/** Sender address (SS58 format) */
|
|
18
|
+
from: string;
|
|
19
|
+
/** Recipient address (SS58 format) */
|
|
20
|
+
to: string;
|
|
21
|
+
/** Amount in smallest unit (with decimals) */
|
|
22
|
+
amount: string;
|
|
23
|
+
/** Asset ID */
|
|
24
|
+
assetId: number;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Result of a Polkadot extrinsic query
|
|
28
|
+
*/
|
|
29
|
+
interface PolkadotExtrinsicResult {
|
|
30
|
+
/** Extrinsic hash */
|
|
31
|
+
extrinsicHash: string;
|
|
32
|
+
/** Block hash */
|
|
33
|
+
blockHash: string;
|
|
34
|
+
/** Block number */
|
|
35
|
+
blockNumber: number;
|
|
36
|
+
/** Extrinsic index */
|
|
37
|
+
extrinsicIndex: number;
|
|
38
|
+
/** Timestamp (ISO 8601) */
|
|
39
|
+
timestamp: string;
|
|
40
|
+
/** Signer address */
|
|
41
|
+
signer: string;
|
|
42
|
+
/** Success status */
|
|
43
|
+
success: boolean;
|
|
44
|
+
/** Module name (e.g., "assets") */
|
|
45
|
+
module: string;
|
|
46
|
+
/** Call name (e.g., "transfer") */
|
|
47
|
+
call: string;
|
|
48
|
+
/** Call arguments */
|
|
49
|
+
args: Record<string, unknown>;
|
|
50
|
+
/** Events emitted by the extrinsic */
|
|
51
|
+
events: PolkadotEvent[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Polkadot event structure
|
|
55
|
+
*/
|
|
56
|
+
interface PolkadotEvent {
|
|
57
|
+
/** Module name */
|
|
58
|
+
module: string;
|
|
59
|
+
/** Event name */
|
|
60
|
+
name: string;
|
|
61
|
+
/** Event data */
|
|
62
|
+
data: Record<string, unknown>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Parsed asset transfer from extrinsic
|
|
66
|
+
*/
|
|
67
|
+
interface ParsedAssetTransfer {
|
|
68
|
+
/** Asset ID */
|
|
69
|
+
assetId: number;
|
|
70
|
+
/** Sender address */
|
|
71
|
+
from: string;
|
|
72
|
+
/** Recipient address */
|
|
73
|
+
to: string;
|
|
74
|
+
/** Amount transferred */
|
|
75
|
+
amount: string;
|
|
76
|
+
/** Whether the transfer was successful */
|
|
77
|
+
success: boolean;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Signer interface for Polkadot facilitator
|
|
81
|
+
*/
|
|
82
|
+
interface FacilitatorPolkadotSigner {
|
|
83
|
+
/**
|
|
84
|
+
* Get the facilitator's addresses for a network
|
|
85
|
+
*/
|
|
86
|
+
getAddresses(network: Network): string[];
|
|
87
|
+
/**
|
|
88
|
+
* Query an extrinsic by hash
|
|
89
|
+
*/
|
|
90
|
+
queryExtrinsic(extrinsicHash: string, blockHash?: string, extrinsicIndex?: number): Promise<PolkadotExtrinsicResult | null>;
|
|
91
|
+
/**
|
|
92
|
+
* Get balance of an asset for an address
|
|
93
|
+
*/
|
|
94
|
+
getBalance(assetId: number, address: string): Promise<string>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Client signer interface for signing transactions
|
|
98
|
+
*/
|
|
99
|
+
interface ClientPolkadotSigner {
|
|
100
|
+
/**
|
|
101
|
+
* Get the signer's address
|
|
102
|
+
*/
|
|
103
|
+
getAddress(): Promise<string>;
|
|
104
|
+
/**
|
|
105
|
+
* Sign and submit an asset transfer
|
|
106
|
+
* Returns the extrinsic hash, block hash, and extrinsic index
|
|
107
|
+
*/
|
|
108
|
+
transferAsset(assetId: number, to: string, amount: string): Promise<{
|
|
109
|
+
extrinsicHash: string;
|
|
110
|
+
blockHash: string;
|
|
111
|
+
extrinsicIndex: number;
|
|
112
|
+
}>;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Configuration for Polkadot server
|
|
116
|
+
*/
|
|
117
|
+
interface PolkadotServerConfig {
|
|
118
|
+
/** Custom RPC URL */
|
|
119
|
+
rpcUrl?: string;
|
|
120
|
+
/** Custom indexer URL */
|
|
121
|
+
indexerUrl?: string;
|
|
122
|
+
/** Facilitator addresses per network */
|
|
123
|
+
facilitatorAddresses?: Record<string, string>;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Configuration for Polkadot facilitator
|
|
127
|
+
*/
|
|
128
|
+
interface PolkadotFacilitatorConfig {
|
|
129
|
+
/** Maximum age of extrinsic to accept (in seconds) */
|
|
130
|
+
maxExtrinsicAge?: number;
|
|
131
|
+
/** Duration to cache used extrinsic hashes */
|
|
132
|
+
usedExtrinsicCacheDuration?: number;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export type { ClientPolkadotSigner as C, ExactDirectPolkadotPayload as E, FacilitatorPolkadotSigner as F, PolkadotExtrinsicResult as P, ParsedAssetTransfer as a, PolkadotEvent as b, PolkadotServerConfig as c, PolkadotFacilitatorConfig as d };
|
package/package.json
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@t402/polkadot",
|
|
3
|
+
"version": "2.3.0",
|
|
4
|
+
"description": "T402 Polkadot Asset Hub mechanism - USDT payments on Polkadot",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/cjs/index.cjs",
|
|
7
|
+
"module": "./dist/esm/index.mjs",
|
|
8
|
+
"types": "./dist/esm/index.d.mts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/esm/index.d.mts",
|
|
13
|
+
"default": "./dist/esm/index.mjs"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/cjs/index.d.cts",
|
|
17
|
+
"default": "./dist/cjs/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"./exact-direct/client": {
|
|
21
|
+
"import": {
|
|
22
|
+
"types": "./dist/esm/exact-direct/client/index.d.mts",
|
|
23
|
+
"default": "./dist/esm/exact-direct/client/index.mjs"
|
|
24
|
+
},
|
|
25
|
+
"require": {
|
|
26
|
+
"types": "./dist/cjs/exact-direct/client/index.d.cts",
|
|
27
|
+
"default": "./dist/cjs/exact-direct/client/index.cjs"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"./exact-direct/server": {
|
|
31
|
+
"import": {
|
|
32
|
+
"types": "./dist/esm/exact-direct/server/index.d.mts",
|
|
33
|
+
"default": "./dist/esm/exact-direct/server/index.mjs"
|
|
34
|
+
},
|
|
35
|
+
"require": {
|
|
36
|
+
"types": "./dist/cjs/exact-direct/server/index.d.cts",
|
|
37
|
+
"default": "./dist/cjs/exact-direct/server/index.cjs"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"./exact-direct/facilitator": {
|
|
41
|
+
"import": {
|
|
42
|
+
"types": "./dist/esm/exact-direct/facilitator/index.d.mts",
|
|
43
|
+
"default": "./dist/esm/exact-direct/facilitator/index.mjs"
|
|
44
|
+
},
|
|
45
|
+
"require": {
|
|
46
|
+
"types": "./dist/cjs/exact-direct/facilitator/index.d.cts",
|
|
47
|
+
"default": "./dist/cjs/exact-direct/facilitator/index.cjs"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"files": [
|
|
52
|
+
"dist",
|
|
53
|
+
"src"
|
|
54
|
+
],
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@t402/core": "2.3.0"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"@polkadot/api": ">=12.0.0"
|
|
60
|
+
},
|
|
61
|
+
"peerDependenciesMeta": {
|
|
62
|
+
"@polkadot/api": {
|
|
63
|
+
"optional": true
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@polkadot/api": "^14.0.0",
|
|
68
|
+
"@types/node": "^22.0.0",
|
|
69
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
70
|
+
"tsup": "^8.3.5",
|
|
71
|
+
"typescript": "^5.7.2",
|
|
72
|
+
"vitest": "^3.2.4"
|
|
73
|
+
},
|
|
74
|
+
"keywords": [
|
|
75
|
+
"t402",
|
|
76
|
+
"polkadot",
|
|
77
|
+
"asset-hub",
|
|
78
|
+
"usdt",
|
|
79
|
+
"payments",
|
|
80
|
+
"cryptocurrency",
|
|
81
|
+
"web3"
|
|
82
|
+
],
|
|
83
|
+
"author": "T402 Team",
|
|
84
|
+
"license": "MIT",
|
|
85
|
+
"repository": {
|
|
86
|
+
"type": "git",
|
|
87
|
+
"url": "https://github.com/t402-io/t402.git",
|
|
88
|
+
"directory": "typescript/packages/mechanisms/polkadot"
|
|
89
|
+
},
|
|
90
|
+
"bugs": {
|
|
91
|
+
"url": "https://github.com/t402-io/t402/issues"
|
|
92
|
+
},
|
|
93
|
+
"homepage": "https://t402.io",
|
|
94
|
+
"scripts": {
|
|
95
|
+
"build": "tsup",
|
|
96
|
+
"dev": "tsup --watch",
|
|
97
|
+
"test": "vitest run",
|
|
98
|
+
"test:watch": "vitest",
|
|
99
|
+
"test:coverage": "vitest run --coverage",
|
|
100
|
+
"typecheck": "tsc --noEmit",
|
|
101
|
+
"clean": "rm -rf dist"
|
|
102
|
+
}
|
|
103
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polkadot Asset Hub T402 Constants
|
|
3
|
+
*
|
|
4
|
+
* Polkadot Asset Hub (formerly Statemint) is a common-good parachain
|
|
5
|
+
* that hosts assets like USDT on the Polkadot network.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// CAIP-2 namespace for Polkadot
|
|
9
|
+
export const POLKADOT_CAIP2_NAMESPACE = "polkadot";
|
|
10
|
+
|
|
11
|
+
// CAIP-2 network identifiers (first 32 chars of genesis hash)
|
|
12
|
+
// Polkadot Asset Hub (Parachain ID: 1000)
|
|
13
|
+
export const POLKADOT_ASSET_HUB_CAIP2 = "polkadot:68d56f15f85d3136970ec16946040bc1";
|
|
14
|
+
|
|
15
|
+
// Kusama Asset Hub (Parachain ID: 1000 on Kusama)
|
|
16
|
+
export const KUSAMA_ASSET_HUB_CAIP2 = "polkadot:48239ef607d7928874027a43a67689209727dfb3d3dc5e5b03a39bdc2eda771a";
|
|
17
|
+
|
|
18
|
+
// Westend Asset Hub (Testnet)
|
|
19
|
+
export const WESTEND_ASSET_HUB_CAIP2 = "polkadot:e143f23803ac50e8f6f8e62695d1ce9e";
|
|
20
|
+
|
|
21
|
+
// Scheme identifier
|
|
22
|
+
export const SCHEME_EXACT_DIRECT = "exact-direct";
|
|
23
|
+
|
|
24
|
+
// Default indexers (Subscan API)
|
|
25
|
+
export const DEFAULT_POLKADOT_INDEXER = "https://assethub-polkadot.api.subscan.io";
|
|
26
|
+
export const DEFAULT_KUSAMA_INDEXER = "https://assethub-kusama.api.subscan.io";
|
|
27
|
+
export const DEFAULT_WESTEND_INDEXER = "https://assethub-westend.api.subscan.io";
|
|
28
|
+
|
|
29
|
+
// Default RPC endpoints
|
|
30
|
+
export const DEFAULT_POLKADOT_RPC = "wss://polkadot-asset-hub-rpc.polkadot.io";
|
|
31
|
+
export const DEFAULT_KUSAMA_RPC = "wss://kusama-asset-hub-rpc.polkadot.io";
|
|
32
|
+
export const DEFAULT_WESTEND_RPC = "wss://westend-asset-hub-rpc.polkadot.io";
|
|
33
|
+
|
|
34
|
+
// Network configurations
|
|
35
|
+
export interface PolkadotNetworkConfig {
|
|
36
|
+
readonly name: string;
|
|
37
|
+
readonly caip2: string;
|
|
38
|
+
readonly rpcUrl: string;
|
|
39
|
+
readonly indexerUrl: string;
|
|
40
|
+
readonly genesisHash: string;
|
|
41
|
+
readonly ss58Prefix: number;
|
|
42
|
+
readonly isTestnet: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const POLKADOT_NETWORKS: Record<string, PolkadotNetworkConfig> = {
|
|
46
|
+
[POLKADOT_ASSET_HUB_CAIP2]: {
|
|
47
|
+
name: "Polkadot Asset Hub",
|
|
48
|
+
caip2: POLKADOT_ASSET_HUB_CAIP2,
|
|
49
|
+
rpcUrl: DEFAULT_POLKADOT_RPC,
|
|
50
|
+
indexerUrl: DEFAULT_POLKADOT_INDEXER,
|
|
51
|
+
genesisHash: "0x68d56f15f85d3136970ec16946040bc1752654e906147f7e43e9d539d7c3de2f",
|
|
52
|
+
ss58Prefix: 0, // Polkadot
|
|
53
|
+
isTestnet: false,
|
|
54
|
+
},
|
|
55
|
+
[KUSAMA_ASSET_HUB_CAIP2]: {
|
|
56
|
+
name: "Kusama Asset Hub",
|
|
57
|
+
caip2: KUSAMA_ASSET_HUB_CAIP2,
|
|
58
|
+
rpcUrl: DEFAULT_KUSAMA_RPC,
|
|
59
|
+
indexerUrl: DEFAULT_KUSAMA_INDEXER,
|
|
60
|
+
genesisHash: "0x48239ef607d7928874027a43a67689209727dfb3d3dc5e5b03a39bdc2eda771a",
|
|
61
|
+
ss58Prefix: 2, // Kusama
|
|
62
|
+
isTestnet: false,
|
|
63
|
+
},
|
|
64
|
+
[WESTEND_ASSET_HUB_CAIP2]: {
|
|
65
|
+
name: "Westend Asset Hub",
|
|
66
|
+
caip2: WESTEND_ASSET_HUB_CAIP2,
|
|
67
|
+
rpcUrl: DEFAULT_WESTEND_RPC,
|
|
68
|
+
indexerUrl: DEFAULT_WESTEND_INDEXER,
|
|
69
|
+
genesisHash: "0xe143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e",
|
|
70
|
+
ss58Prefix: 42, // Generic Substrate
|
|
71
|
+
isTestnet: true,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get network configuration by CAIP-2 identifier
|
|
77
|
+
*/
|
|
78
|
+
export function getNetworkConfig(network: string): PolkadotNetworkConfig | undefined {
|
|
79
|
+
return POLKADOT_NETWORKS[network];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Check if a network identifier is a Polkadot network
|
|
84
|
+
*/
|
|
85
|
+
export function isPolkadotNetwork(network: string): boolean {
|
|
86
|
+
return network.startsWith(`${POLKADOT_CAIP2_NAMESPACE}:`);
|
|
87
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polkadot Exact-Direct Client Scheme
|
|
3
|
+
*
|
|
4
|
+
* In the exact-direct scheme, the client executes the asset transfer directly
|
|
5
|
+
* and provides the extrinsic hash as proof of payment.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
PaymentPayload,
|
|
10
|
+
PaymentRequirements,
|
|
11
|
+
SchemeNetworkClient,
|
|
12
|
+
} from "@t402/core/types";
|
|
13
|
+
import type { ClientPolkadotSigner, ExactDirectPolkadotPayload } from "../../types.js";
|
|
14
|
+
import { SCHEME_EXACT_DIRECT, POLKADOT_CAIP2_NAMESPACE } from "../../constants.js";
|
|
15
|
+
import { getAssetId } from "../../tokens.js";
|
|
16
|
+
import { isValidAddress } from "../../utils.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Configuration for the exact-direct client
|
|
20
|
+
*/
|
|
21
|
+
export interface ExactDirectPolkadotClientConfig {
|
|
22
|
+
/** Signer for executing transactions */
|
|
23
|
+
signer: ClientPolkadotSigner;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Exact-direct client scheme for Polkadot Asset Hub
|
|
28
|
+
*/
|
|
29
|
+
export class ExactDirectPolkadotClient implements SchemeNetworkClient {
|
|
30
|
+
readonly scheme = SCHEME_EXACT_DIRECT;
|
|
31
|
+
private readonly signer: ClientPolkadotSigner;
|
|
32
|
+
|
|
33
|
+
constructor(config: ExactDirectPolkadotClientConfig) {
|
|
34
|
+
this.signer = config.signer;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Create a payment payload by executing the transfer
|
|
39
|
+
*/
|
|
40
|
+
async createPaymentPayload(
|
|
41
|
+
t402Version: number,
|
|
42
|
+
requirements: PaymentRequirements,
|
|
43
|
+
): Promise<Pick<PaymentPayload, "t402Version" | "payload">> {
|
|
44
|
+
// Validate requirements
|
|
45
|
+
this.validateRequirements(requirements);
|
|
46
|
+
|
|
47
|
+
const { network, amount, payTo, extra } = requirements;
|
|
48
|
+
|
|
49
|
+
// Get asset ID from extra or use default USDT
|
|
50
|
+
const symbol = (extra?.assetSymbol as string) || "USDT";
|
|
51
|
+
const assetId = (extra?.assetId as number) ?? getAssetId(network, symbol);
|
|
52
|
+
|
|
53
|
+
if (assetId === undefined) {
|
|
54
|
+
throw new Error(`Unknown asset ${symbol} on network ${network}`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Get sender address
|
|
58
|
+
const from = await this.signer.getAddress();
|
|
59
|
+
|
|
60
|
+
// Execute the transfer
|
|
61
|
+
const { extrinsicHash, blockHash, extrinsicIndex } =
|
|
62
|
+
await this.signer.transferAsset(assetId, payTo, amount);
|
|
63
|
+
|
|
64
|
+
// Build the payload
|
|
65
|
+
const polkadotPayload: ExactDirectPolkadotPayload = {
|
|
66
|
+
extrinsicHash,
|
|
67
|
+
blockHash,
|
|
68
|
+
extrinsicIndex,
|
|
69
|
+
from,
|
|
70
|
+
to: payTo,
|
|
71
|
+
amount,
|
|
72
|
+
assetId,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
t402Version,
|
|
77
|
+
payload: polkadotPayload,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Validate payment requirements
|
|
83
|
+
*/
|
|
84
|
+
private validateRequirements(requirements: PaymentRequirements): void {
|
|
85
|
+
// Check scheme
|
|
86
|
+
if (requirements.scheme !== SCHEME_EXACT_DIRECT) {
|
|
87
|
+
throw new Error(
|
|
88
|
+
`Invalid scheme: expected ${SCHEME_EXACT_DIRECT}, got ${requirements.scheme}`,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Check network
|
|
93
|
+
if (!requirements.network.startsWith(`${POLKADOT_CAIP2_NAMESPACE}:`)) {
|
|
94
|
+
throw new Error(`Invalid network: ${requirements.network}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Check payTo address
|
|
98
|
+
if (!isValidAddress(requirements.payTo)) {
|
|
99
|
+
throw new Error(`Invalid payTo address: ${requirements.payTo}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Check amount
|
|
103
|
+
const amount = BigInt(requirements.amount);
|
|
104
|
+
if (amount <= 0n) {
|
|
105
|
+
throw new Error(`Invalid amount: ${requirements.amount}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Create an exact-direct client for Polkadot
|
|
112
|
+
*/
|
|
113
|
+
export function createExactDirectPolkadotClient(
|
|
114
|
+
config: ExactDirectPolkadotClientConfig,
|
|
115
|
+
): ExactDirectPolkadotClient {
|
|
116
|
+
return new ExactDirectPolkadotClient(config);
|
|
117
|
+
}
|