@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
package/src/utils.ts ADDED
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Aptos Utility Functions
3
+ */
4
+
5
+ import type { Network } from "@t402/core/types";
6
+ import {
7
+ APTOS_CAIP2_NAMESPACE,
8
+ APTOS_MAINNET_CAIP2,
9
+ APTOS_TESTNET_CAIP2,
10
+ APTOS_DEVNET_CAIP2,
11
+ DEFAULT_MAINNET_RPC,
12
+ DEFAULT_TESTNET_RPC,
13
+ DEFAULT_DEVNET_RPC,
14
+ FA_TRANSFER_FUNCTION,
15
+ } from "./constants.js";
16
+ import type {
17
+ AptosTransactionResult,
18
+ AptosTransactionEvent,
19
+ ParsedFATransfer,
20
+ } from "./types.js";
21
+
22
+ /**
23
+ * Validate Aptos address format
24
+ * Aptos addresses are 64 hex characters (32 bytes) with 0x prefix
25
+ */
26
+ export function isValidAptosAddress(address: string): boolean {
27
+ if (!address) return false;
28
+ // Must start with 0x
29
+ if (!address.startsWith("0x")) return false;
30
+ // Remove 0x prefix and check hex
31
+ const hex = address.slice(2);
32
+ // Aptos addresses can be 1-64 hex chars (leading zeros may be omitted)
33
+ if (hex.length === 0 || hex.length > 64) return false;
34
+ return /^[0-9a-fA-F]+$/.test(hex);
35
+ }
36
+
37
+ /**
38
+ * Normalize Aptos address to full 64-character format
39
+ */
40
+ export function normalizeAptosAddress(address: string): string {
41
+ if (!address.startsWith("0x")) {
42
+ throw new Error("Aptos address must start with 0x");
43
+ }
44
+ const hex = address.slice(2).toLowerCase();
45
+ // Pad to 64 characters
46
+ return "0x" + hex.padStart(64, "0");
47
+ }
48
+
49
+ /**
50
+ * Compare two Aptos addresses (case-insensitive, handles short addresses)
51
+ */
52
+ export function compareAddresses(addr1: string, addr2: string): boolean {
53
+ try {
54
+ return normalizeAptosAddress(addr1) === normalizeAptosAddress(addr2);
55
+ } catch {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Validate transaction hash format
62
+ */
63
+ export function isValidTxHash(txHash: string): boolean {
64
+ if (!txHash) return false;
65
+ if (!txHash.startsWith("0x")) return false;
66
+ const hex = txHash.slice(2);
67
+ // Transaction hash is 64 hex characters (32 bytes)
68
+ if (hex.length !== 64) return false;
69
+ return /^[0-9a-fA-F]+$/.test(hex);
70
+ }
71
+
72
+ /**
73
+ * Get default RPC URL for a network
74
+ */
75
+ export function getDefaultRpcUrl(network: Network): string {
76
+ switch (network) {
77
+ case APTOS_MAINNET_CAIP2:
78
+ return DEFAULT_MAINNET_RPC;
79
+ case APTOS_TESTNET_CAIP2:
80
+ return DEFAULT_TESTNET_RPC;
81
+ case APTOS_DEVNET_CAIP2:
82
+ return DEFAULT_DEVNET_RPC;
83
+ default:
84
+ throw new Error(`Unknown Aptos network: ${network}`);
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Check if a network identifier is for Aptos
90
+ */
91
+ export function isAptosNetwork(network: Network): boolean {
92
+ return network.startsWith(`${APTOS_CAIP2_NAMESPACE}:`);
93
+ }
94
+
95
+ /**
96
+ * Parse CAIP-19 asset identifier for Aptos
97
+ * Format: aptos:1/fa:0x...
98
+ */
99
+ export function parseAssetIdentifier(asset: string): {
100
+ network: Network;
101
+ metadataAddress: string;
102
+ } | null {
103
+ const parts = asset.split("/");
104
+ if (parts.length !== 2) return null;
105
+
106
+ const network = parts[0] as Network;
107
+ if (!isAptosNetwork(network)) return null;
108
+
109
+ const [assetType, address] = parts[1].split(":");
110
+ if (assetType !== "fa" || !address) return null;
111
+
112
+ if (!isValidAptosAddress(address)) return null;
113
+
114
+ return { network, metadataAddress: address };
115
+ }
116
+
117
+ /**
118
+ * Create CAIP-19 asset identifier for Aptos FA
119
+ */
120
+ export function createAssetIdentifier(
121
+ network: Network,
122
+ metadataAddress: string,
123
+ ): string {
124
+ return `${network}/fa:${metadataAddress}`;
125
+ }
126
+
127
+ /**
128
+ * Parse fungible asset transfer from transaction events
129
+ */
130
+ export function parseFATransferFromEvents(
131
+ events: AptosTransactionEvent[],
132
+ ): ParsedFATransfer | null {
133
+ // Look for Withdraw and Deposit events
134
+ const withdrawEvent = events.find(
135
+ (e) =>
136
+ e.type === "0x1::fungible_asset::Withdraw" ||
137
+ e.type.includes("::fungible_asset::Withdraw"),
138
+ );
139
+ const depositEvent = events.find(
140
+ (e) =>
141
+ e.type === "0x1::fungible_asset::Deposit" ||
142
+ e.type.includes("::fungible_asset::Deposit"),
143
+ );
144
+
145
+ if (!withdrawEvent || !depositEvent) {
146
+ return null;
147
+ }
148
+
149
+ // Extract data from events
150
+ const withdrawData = withdrawEvent.data as {
151
+ store?: string;
152
+ amount?: string;
153
+ };
154
+ const depositData = depositEvent.data as {
155
+ store?: string;
156
+ amount?: string;
157
+ };
158
+
159
+ if (!withdrawData.amount || !depositData.store) {
160
+ return null;
161
+ }
162
+
163
+ // The from address is the account that owns the withdraw store
164
+ // The to address is the account that owns the deposit store
165
+ // For simplicity, we'll extract from the event guid
166
+ const from = withdrawEvent.guid.accountAddress;
167
+ const to = depositEvent.guid.accountAddress;
168
+ const amount = BigInt(withdrawData.amount);
169
+
170
+ // Metadata address would need to be extracted from state changes
171
+ // For now, return with empty metadata (to be filled by caller)
172
+ return {
173
+ from,
174
+ to,
175
+ amount,
176
+ metadataAddress: "", // Will be filled from transaction details
177
+ };
178
+ }
179
+
180
+ /**
181
+ * Check if transaction is a FA transfer
182
+ */
183
+ export function isFATransferTransaction(tx: AptosTransactionResult): boolean {
184
+ if (!tx.payload) return false;
185
+ if (tx.payload.type !== "entry_function_payload") return false;
186
+ return (
187
+ tx.payload.function === FA_TRANSFER_FUNCTION ||
188
+ tx.payload.function?.includes("primary_fungible_store::transfer") ||
189
+ false
190
+ );
191
+ }
192
+
193
+ /**
194
+ * Extract transfer details from transaction
195
+ */
196
+ export function extractTransferDetails(
197
+ tx: AptosTransactionResult,
198
+ ): ParsedFATransfer | null {
199
+ if (!tx.success) return null;
200
+ if (!tx.payload || tx.payload.type !== "entry_function_payload") return null;
201
+
202
+ const args = tx.payload.arguments;
203
+ if (!args || args.length < 3) return null;
204
+
205
+ // Arguments for primary_fungible_store::transfer:
206
+ // [0] - metadata object address
207
+ // [1] - recipient address
208
+ // [2] - amount
209
+
210
+ const metadataAddress = args[0] as string;
211
+ const to = args[1] as string;
212
+ const amount = BigInt(args[2] as string);
213
+
214
+ return {
215
+ from: tx.sender,
216
+ to,
217
+ amount,
218
+ metadataAddress,
219
+ };
220
+ }
221
+
222
+ /**
223
+ * Format amount with decimals for display
224
+ */
225
+ export function formatAmount(amount: bigint, decimals: number): string {
226
+ const divisor = BigInt(10 ** decimals);
227
+ const wholePart = amount / divisor;
228
+ const fractionalPart = amount % divisor;
229
+ const paddedFractional = fractionalPart.toString().padStart(decimals, "0");
230
+ return `${wholePart}.${paddedFractional}`;
231
+ }
232
+
233
+ /**
234
+ * Parse amount string to bigint
235
+ */
236
+ export function parseAmount(amount: string, decimals: number): bigint {
237
+ const [whole, fractional = ""] = amount.split(".");
238
+ const paddedFractional = fractional.padEnd(decimals, "0").slice(0, decimals);
239
+ return BigInt(whole + paddedFractional);
240
+ }