@t402/aptos 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 (42) hide show
  1. package/README.md +171 -0
  2. package/dist/exact-direct/client/index.d.cts +91 -0
  3. package/dist/exact-direct/client/index.d.ts +91 -0
  4. package/dist/exact-direct/client/index.js +203 -0
  5. package/dist/exact-direct/client/index.js.map +1 -0
  6. package/dist/exact-direct/client/index.mjs +175 -0
  7. package/dist/exact-direct/client/index.mjs.map +1 -0
  8. package/dist/exact-direct/facilitator/index.d.cts +110 -0
  9. package/dist/exact-direct/facilitator/index.d.ts +110 -0
  10. package/dist/exact-direct/facilitator/index.js +352 -0
  11. package/dist/exact-direct/facilitator/index.js.map +1 -0
  12. package/dist/exact-direct/facilitator/index.mjs +324 -0
  13. package/dist/exact-direct/facilitator/index.mjs.map +1 -0
  14. package/dist/exact-direct/server/index.d.cts +106 -0
  15. package/dist/exact-direct/server/index.d.ts +106 -0
  16. package/dist/exact-direct/server/index.js +220 -0
  17. package/dist/exact-direct/server/index.js.map +1 -0
  18. package/dist/exact-direct/server/index.mjs +192 -0
  19. package/dist/exact-direct/server/index.mjs.map +1 -0
  20. package/dist/index.d.cts +145 -0
  21. package/dist/index.d.ts +145 -0
  22. package/dist/index.js +759 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/index.mjs +687 -0
  25. package/dist/index.mjs.map +1 -0
  26. package/dist/types-kOweBf4U.d.cts +149 -0
  27. package/dist/types-kOweBf4U.d.ts +149 -0
  28. package/package.json +100 -0
  29. package/src/constants.ts +48 -0
  30. package/src/exact-direct/client/index.ts +12 -0
  31. package/src/exact-direct/client/register.ts +83 -0
  32. package/src/exact-direct/client/scheme.ts +148 -0
  33. package/src/exact-direct/facilitator/index.ts +12 -0
  34. package/src/exact-direct/facilitator/register.ts +74 -0
  35. package/src/exact-direct/facilitator/scheme.ts +300 -0
  36. package/src/exact-direct/server/index.ts +12 -0
  37. package/src/exact-direct/server/register.ts +65 -0
  38. package/src/exact-direct/server/scheme.ts +196 -0
  39. package/src/index.ts +58 -0
  40. package/src/tokens.ts +114 -0
  41. package/src/types.ts +174 -0
  42. package/src/utils.ts +240 -0
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Aptos Exact-Direct Server Scheme
3
+ *
4
+ * Handles price parsing and payment requirement enhancement for
5
+ * Aptos FA 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 } from "../../constants.js";
17
+ import { getTokenConfig, getDefaultToken, TOKEN_REGISTRY } from "../../tokens.js";
18
+ import {
19
+ isAptosNetwork,
20
+ createAssetIdentifier,
21
+ parseAmount,
22
+ } from "../../utils.js";
23
+
24
+ /**
25
+ * Configuration for ExactDirectAptosServer
26
+ */
27
+ export interface ExactDirectAptosServerConfig {
28
+ /** Preferred token symbol (e.g., "USDT"). Defaults to network's default token. */
29
+ preferredToken?: string;
30
+ }
31
+
32
+ /**
33
+ * Aptos Exact-Direct Server
34
+ *
35
+ * Implements the server-side price parsing and payment requirements enhancement.
36
+ */
37
+ export class ExactDirectAptosServer implements SchemeNetworkServer {
38
+ readonly scheme = SCHEME_EXACT_DIRECT;
39
+ private moneyParsers: MoneyParser[] = [];
40
+ private config: ExactDirectAptosServerConfig;
41
+
42
+ constructor(config: ExactDirectAptosServerConfig = {}) {
43
+ this.config = config;
44
+ }
45
+
46
+ /**
47
+ * Register a custom money parser in the parser chain.
48
+ */
49
+ registerMoneyParser(parser: MoneyParser): ExactDirectAptosServer {
50
+ this.moneyParsers.push(parser);
51
+ return this;
52
+ }
53
+
54
+ /**
55
+ * Parse price into Aptos-specific amount
56
+ */
57
+ async parsePrice(price: Price, network: Network): Promise<AssetAmount> {
58
+ // Validate network
59
+ if (!isAptosNetwork(network)) {
60
+ throw new Error(`Invalid Aptos network: ${network}`);
61
+ }
62
+
63
+ // If already an AssetAmount, return it directly
64
+ if (typeof price === "object" && price !== null && "amount" in price) {
65
+ if (!price.asset) {
66
+ throw new Error(`Asset address must be specified for AssetAmount on network ${network}`);
67
+ }
68
+ return {
69
+ amount: price.amount,
70
+ asset: price.asset,
71
+ extra: price.extra || {},
72
+ };
73
+ }
74
+
75
+ // Parse Money to decimal number
76
+ const amount = this.parseMoneyToDecimal(price);
77
+
78
+ // Try each custom money parser in order
79
+ for (const parser of this.moneyParsers) {
80
+ const result = await parser(amount, network);
81
+ if (result !== null) {
82
+ return result;
83
+ }
84
+ }
85
+
86
+ // All custom parsers returned null, use default conversion
87
+ return this.defaultMoneyConversion(amount, network);
88
+ }
89
+
90
+ /**
91
+ * Enhance payment requirements with Aptos-specific details
92
+ */
93
+ async enhancePaymentRequirements(
94
+ paymentRequirements: PaymentRequirements,
95
+ supportedKind: {
96
+ t402Version: number;
97
+ scheme: string;
98
+ network: Network;
99
+ extra?: Record<string, unknown>;
100
+ },
101
+ facilitatorExtensions: string[],
102
+ ): Promise<PaymentRequirements> {
103
+ // Mark unused parameters
104
+ void facilitatorExtensions;
105
+
106
+ // Start with existing extra fields
107
+ const extra = { ...paymentRequirements.extra };
108
+
109
+ // Add any facilitator-provided extra fields
110
+ if (supportedKind.extra?.assetSymbol) {
111
+ extra.assetSymbol = supportedKind.extra.assetSymbol;
112
+ }
113
+ if (supportedKind.extra?.assetDecimals) {
114
+ extra.assetDecimals = supportedKind.extra.assetDecimals;
115
+ }
116
+
117
+ return {
118
+ ...paymentRequirements,
119
+ extra,
120
+ };
121
+ }
122
+
123
+ /**
124
+ * Parse Money (string | number) to a decimal number.
125
+ */
126
+ private parseMoneyToDecimal(money: string | number): number {
127
+ if (typeof money === "number") {
128
+ return money;
129
+ }
130
+
131
+ // Remove $ sign and whitespace, then parse
132
+ const cleanMoney = money.replace(/^\$/, "").trim();
133
+ const amount = parseFloat(cleanMoney);
134
+
135
+ if (isNaN(amount)) {
136
+ throw new Error(`Invalid money format: ${money}`);
137
+ }
138
+
139
+ return amount;
140
+ }
141
+
142
+ /**
143
+ * Default money conversion implementation.
144
+ */
145
+ private defaultMoneyConversion(amount: number, network: Network): AssetAmount {
146
+ const token = this.getDefaultAsset(network);
147
+
148
+ // Convert decimal amount to token amount
149
+ const tokenAmount = parseAmount(amount.toString(), token.decimals);
150
+
151
+ return {
152
+ amount: tokenAmount.toString(),
153
+ asset: createAssetIdentifier(network, token.metadataAddress),
154
+ extra: {
155
+ symbol: token.symbol,
156
+ name: token.name,
157
+ decimals: token.decimals,
158
+ },
159
+ };
160
+ }
161
+
162
+ /**
163
+ * Get the default asset info for a network.
164
+ */
165
+ private getDefaultAsset(
166
+ network: Network,
167
+ ): { metadataAddress: string; symbol: string; name: string; decimals: number } {
168
+ // If a preferred token is configured, try to use it
169
+ if (this.config.preferredToken) {
170
+ const preferred = getTokenConfig(network, this.config.preferredToken);
171
+ if (preferred) return preferred;
172
+ }
173
+
174
+ // Use the network's default token
175
+ const defaultToken = getDefaultToken(network);
176
+ if (defaultToken) return defaultToken;
177
+
178
+ throw new Error(`No tokens configured for network ${network}`);
179
+ }
180
+
181
+ /**
182
+ * Get all supported networks
183
+ */
184
+ static getSupportedNetworks(): string[] {
185
+ return Object.keys(TOKEN_REGISTRY);
186
+ }
187
+
188
+ /**
189
+ * Check if a network is supported
190
+ */
191
+ static isNetworkSupported(network: string): boolean {
192
+ return network in TOKEN_REGISTRY;
193
+ }
194
+ }
195
+
196
+ export default ExactDirectAptosServer;
package/src/index.ts ADDED
@@ -0,0 +1,58 @@
1
+ /**
2
+ * @t402/aptos - Aptos (Move) mechanism for T402 payment protocol
3
+ *
4
+ * This package provides support for Aptos blockchain payments using
5
+ * the Fungible Asset (FA) standard.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // Client usage
10
+ * import { registerExactDirectAptosClient } from "@t402/aptos/exact-direct/client";
11
+ * import { t402Client } from "@t402/core/client";
12
+ *
13
+ * const client = new t402Client();
14
+ * registerExactDirectAptosClient(client, {
15
+ * signer: myAptosSigner,
16
+ * networks: "aptos:1"
17
+ * });
18
+ *
19
+ * // Server usage
20
+ * import { registerExactDirectAptosServer } from "@t402/aptos/exact-direct/server";
21
+ * import { t402ResourceServer } from "@t402/core/server";
22
+ *
23
+ * const server = new t402ResourceServer();
24
+ * registerExactDirectAptosServer(server, {
25
+ * networks: "aptos:1",
26
+ * schemeConfig: { defaultPayTo: "0x..." }
27
+ * });
28
+ *
29
+ * // Facilitator usage
30
+ * import { registerExactDirectAptosFacilitator } from "@t402/aptos/exact-direct/facilitator";
31
+ * import { t402Facilitator } from "@t402/core/facilitator";
32
+ *
33
+ * const facilitator = new t402Facilitator();
34
+ * registerExactDirectAptosFacilitator(facilitator, {
35
+ * signer: myAptosSigner,
36
+ * networks: "aptos:1"
37
+ * });
38
+ * ```
39
+ *
40
+ * @packageDocumentation
41
+ */
42
+
43
+ // Constants
44
+ export * from "./constants.js";
45
+
46
+ // Types
47
+ export * from "./types.js";
48
+
49
+ // Token registry
50
+ export * from "./tokens.js";
51
+
52
+ // Utility functions
53
+ export * from "./utils.js";
54
+
55
+ // Re-export scheme modules for convenience
56
+ export * from "./exact-direct/client/index.js";
57
+ export * from "./exact-direct/server/index.js";
58
+ export * from "./exact-direct/facilitator/index.js";
package/src/tokens.ts ADDED
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Aptos Token Registry
3
+ *
4
+ * Token addresses for supported stablecoins on Aptos networks.
5
+ * All tokens use the Fungible Asset (FA) standard.
6
+ */
7
+
8
+ import {
9
+ APTOS_MAINNET_CAIP2,
10
+ APTOS_TESTNET_CAIP2,
11
+ APTOS_DEVNET_CAIP2,
12
+ } from "./constants.js";
13
+
14
+ /**
15
+ * Token configuration for Aptos fungible assets
16
+ */
17
+ export interface TokenConfig {
18
+ /** Fungible Asset metadata address */
19
+ metadataAddress: string;
20
+ /** Token symbol (e.g., "USDT", "USDC") */
21
+ symbol: string;
22
+ /** Token name */
23
+ name: string;
24
+ /** Decimal places */
25
+ decimals: number;
26
+ }
27
+
28
+ /**
29
+ * Token registry mapping network -> tokens
30
+ */
31
+ export const TOKEN_REGISTRY: Record<string, TokenConfig[]> = {
32
+ [APTOS_MAINNET_CAIP2]: [
33
+ {
34
+ metadataAddress:
35
+ "0xf73e887a8754f540ee6e1a93bdc6dde2af69fc7ca5de32013e89dd44244473cb",
36
+ symbol: "USDT",
37
+ name: "Tether USD",
38
+ decimals: 6,
39
+ },
40
+ {
41
+ metadataAddress:
42
+ "0xbae207659db88bea0cbead6da0ed00aac12edcdda169e591cd41c94180b46f3b",
43
+ symbol: "USDC",
44
+ name: "USD Coin",
45
+ decimals: 6,
46
+ },
47
+ ],
48
+ [APTOS_TESTNET_CAIP2]: [
49
+ {
50
+ // Testnet USDT (may differ from mainnet)
51
+ metadataAddress:
52
+ "0xf73e887a8754f540ee6e1a93bdc6dde2af69fc7ca5de32013e89dd44244473cb",
53
+ symbol: "USDT",
54
+ name: "Tether USD",
55
+ decimals: 6,
56
+ },
57
+ ],
58
+ [APTOS_DEVNET_CAIP2]: [],
59
+ };
60
+
61
+ /**
62
+ * Get token configuration for a specific network and symbol
63
+ */
64
+ export function getTokenConfig(
65
+ network: string,
66
+ symbol: string,
67
+ ): TokenConfig | undefined {
68
+ const tokens = TOKEN_REGISTRY[network];
69
+ if (!tokens) return undefined;
70
+ return tokens.find(
71
+ (t) => t.symbol.toUpperCase() === symbol.toUpperCase(),
72
+ );
73
+ }
74
+
75
+ /**
76
+ * Get all supported tokens for a network
77
+ */
78
+ export function getSupportedTokens(network: string): TokenConfig[] {
79
+ return TOKEN_REGISTRY[network] || [];
80
+ }
81
+
82
+ /**
83
+ * Check if a token is supported on a network
84
+ */
85
+ export function isTokenSupported(network: string, symbol: string): boolean {
86
+ return getTokenConfig(network, symbol) !== undefined;
87
+ }
88
+
89
+ /**
90
+ * Get token by metadata address
91
+ */
92
+ export function getTokenByAddress(
93
+ network: string,
94
+ metadataAddress: string,
95
+ ): TokenConfig | undefined {
96
+ const tokens = TOKEN_REGISTRY[network];
97
+ if (!tokens) return undefined;
98
+ const normalizedAddress = metadataAddress.toLowerCase();
99
+ return tokens.find(
100
+ (t) => t.metadataAddress.toLowerCase() === normalizedAddress,
101
+ );
102
+ }
103
+
104
+ /**
105
+ * Default token symbol for payments (USDT)
106
+ */
107
+ export const DEFAULT_TOKEN_SYMBOL = "USDT";
108
+
109
+ /**
110
+ * Get the default token for a network
111
+ */
112
+ export function getDefaultToken(network: string): TokenConfig | undefined {
113
+ return getTokenConfig(network, DEFAULT_TOKEN_SYMBOL);
114
+ }
package/src/types.ts ADDED
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Aptos Types for T402 Payment Protocol
3
+ */
4
+
5
+ import type { Network } from "@t402/core/types";
6
+
7
+ /**
8
+ * Exact-direct payment payload for Aptos
9
+ * Client executes the transfer and provides transaction hash as proof
10
+ */
11
+ export type ExactDirectAptosPayload = {
12
+ /** Transaction hash (hex string with 0x prefix) */
13
+ txHash: string;
14
+ /** Sender's Aptos address */
15
+ from: string;
16
+ /** Recipient's Aptos address */
17
+ to: string;
18
+ /** Amount transferred (in smallest unit) */
19
+ amount: string;
20
+ /** Fungible Asset metadata address */
21
+ metadataAddress: string;
22
+ /** Transaction version (for verification) */
23
+ version?: string;
24
+ };
25
+
26
+ /**
27
+ * Aptos signer interface for client operations
28
+ */
29
+ export interface ClientAptosSigner {
30
+ /**
31
+ * Get the signer's Aptos address
32
+ */
33
+ getAddress(): Promise<string>;
34
+
35
+ /**
36
+ * Sign and submit a fungible asset transfer transaction
37
+ * @param to Recipient address
38
+ * @param metadataAddress FA metadata address
39
+ * @param amount Amount to transfer
40
+ * @returns Transaction hash
41
+ */
42
+ transfer(
43
+ to: string,
44
+ metadataAddress: string,
45
+ amount: bigint,
46
+ ): Promise<string>;
47
+
48
+ /**
49
+ * Get token balance for an address
50
+ * @param metadataAddress FA metadata address
51
+ * @returns Balance in smallest unit
52
+ */
53
+ getBalance(metadataAddress: string): Promise<bigint>;
54
+ }
55
+
56
+ /**
57
+ * Aptos signer interface for facilitator operations
58
+ */
59
+ export interface FacilitatorAptosSigner {
60
+ /**
61
+ * Get facilitator addresses for a network
62
+ * @param network CAIP-2 network identifier
63
+ */
64
+ getAddresses(network: Network): string[];
65
+
66
+ /**
67
+ * Query transaction by hash
68
+ * @param txHash Transaction hash
69
+ * @returns Transaction details or null if not found
70
+ */
71
+ queryTransaction(txHash: string): Promise<AptosTransactionResult | null>;
72
+
73
+ /**
74
+ * Get token balance for an address
75
+ * @param address Account address
76
+ * @param metadataAddress FA metadata address
77
+ * @returns Balance in smallest unit
78
+ */
79
+ getBalance(address: string, metadataAddress: string): Promise<bigint>;
80
+ }
81
+
82
+ /**
83
+ * Aptos transaction result from RPC
84
+ */
85
+ export interface AptosTransactionResult {
86
+ /** Transaction hash */
87
+ hash: string;
88
+ /** Transaction version */
89
+ version: string;
90
+ /** Whether the transaction was successful */
91
+ success: boolean;
92
+ /** VM status */
93
+ vmStatus: string;
94
+ /** Sender address */
95
+ sender: string;
96
+ /** Sequence number */
97
+ sequenceNumber: string;
98
+ /** Gas used */
99
+ gasUsed: string;
100
+ /** Timestamp (microseconds) */
101
+ timestamp: string;
102
+ /** Transaction payload */
103
+ payload?: AptosTransactionPayload;
104
+ /** Events emitted by the transaction */
105
+ events?: AptosTransactionEvent[];
106
+ /** State changes */
107
+ changes?: AptosStateChange[];
108
+ }
109
+
110
+ /**
111
+ * Aptos transaction payload
112
+ */
113
+ export interface AptosTransactionPayload {
114
+ type: string;
115
+ function?: string;
116
+ typeArguments?: string[];
117
+ arguments?: unknown[];
118
+ }
119
+
120
+ /**
121
+ * Aptos transaction event
122
+ */
123
+ export interface AptosTransactionEvent {
124
+ guid: {
125
+ creationNumber: string;
126
+ accountAddress: string;
127
+ };
128
+ sequenceNumber: string;
129
+ type: string;
130
+ data: Record<string, unknown>;
131
+ }
132
+
133
+ /**
134
+ * Aptos state change
135
+ */
136
+ export interface AptosStateChange {
137
+ type: string;
138
+ address: string;
139
+ stateKeyHash: string;
140
+ data?: {
141
+ type: string;
142
+ data: Record<string, unknown>;
143
+ };
144
+ }
145
+
146
+ /**
147
+ * Parsed fungible asset transfer from events
148
+ */
149
+ export interface ParsedFATransfer {
150
+ /** Sender address */
151
+ from: string;
152
+ /** Recipient address */
153
+ to: string;
154
+ /** Amount transferred */
155
+ amount: bigint;
156
+ /** FA metadata address */
157
+ metadataAddress: string;
158
+ }
159
+
160
+ /**
161
+ * Extract Aptos chain ID from CAIP-2 network identifier
162
+ */
163
+ export function extractChainId(network: Network): number {
164
+ const parts = network.split(":");
165
+ if (parts.length !== 2 || parts[0] !== "aptos") {
166
+ throw new Error(`Invalid Aptos network identifier: ${network}`);
167
+ }
168
+ const chainId = parseInt(parts[1], 10);
169
+ if (isNaN(chainId)) {
170
+ throw new Error(`Invalid chain ID in network identifier: ${network}`);
171
+ }
172
+ return chainId;
173
+ }
174
+