@mantle-rwa/sdk 0.1.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 (79) hide show
  1. package/dist/cjs/client.js +198 -0
  2. package/dist/cjs/client.js.map +1 -0
  3. package/dist/cjs/constants/index.js +211 -0
  4. package/dist/cjs/constants/index.js.map +1 -0
  5. package/dist/cjs/errors/index.js +218 -0
  6. package/dist/cjs/errors/index.js.map +1 -0
  7. package/dist/cjs/index.js +51 -0
  8. package/dist/cjs/index.js.map +1 -0
  9. package/dist/cjs/modules/compliance.js +202 -0
  10. package/dist/cjs/modules/compliance.js.map +1 -0
  11. package/dist/cjs/modules/index.js +18 -0
  12. package/dist/cjs/modules/index.js.map +1 -0
  13. package/dist/cjs/modules/kyc.js +278 -0
  14. package/dist/cjs/modules/kyc.js.map +1 -0
  15. package/dist/cjs/modules/token.js +365 -0
  16. package/dist/cjs/modules/token.js.map +1 -0
  17. package/dist/cjs/modules/yield.js +406 -0
  18. package/dist/cjs/modules/yield.js.map +1 -0
  19. package/dist/cjs/package.json +3 -0
  20. package/dist/cjs/types/index.js +20 -0
  21. package/dist/cjs/types/index.js.map +1 -0
  22. package/dist/cjs/utils/index.js +206 -0
  23. package/dist/cjs/utils/index.js.map +1 -0
  24. package/dist/esm/client.js +194 -0
  25. package/dist/esm/client.js.map +1 -0
  26. package/dist/esm/constants/index.js +208 -0
  27. package/dist/esm/constants/index.js.map +1 -0
  28. package/dist/esm/errors/index.js +209 -0
  29. package/dist/esm/errors/index.js.map +1 -0
  30. package/dist/esm/index.js +17 -0
  31. package/dist/esm/index.js.map +1 -0
  32. package/dist/esm/modules/compliance.js +198 -0
  33. package/dist/esm/modules/compliance.js.map +1 -0
  34. package/dist/esm/modules/index.js +8 -0
  35. package/dist/esm/modules/index.js.map +1 -0
  36. package/dist/esm/modules/kyc.js +273 -0
  37. package/dist/esm/modules/kyc.js.map +1 -0
  38. package/dist/esm/modules/token.js +360 -0
  39. package/dist/esm/modules/token.js.map +1 -0
  40. package/dist/esm/modules/yield.js +401 -0
  41. package/dist/esm/modules/yield.js.map +1 -0
  42. package/dist/esm/types/index.js +17 -0
  43. package/dist/esm/types/index.js.map +1 -0
  44. package/dist/esm/utils/index.js +188 -0
  45. package/dist/esm/utils/index.js.map +1 -0
  46. package/dist/types/client.d.ts +93 -0
  47. package/dist/types/client.d.ts.map +1 -0
  48. package/dist/types/constants/index.d.ts +83 -0
  49. package/dist/types/constants/index.d.ts.map +1 -0
  50. package/dist/types/errors/index.d.ts +83 -0
  51. package/dist/types/errors/index.d.ts.map +1 -0
  52. package/dist/types/index.d.ts +13 -0
  53. package/dist/types/index.d.ts.map +1 -0
  54. package/dist/types/modules/compliance.d.ts +29 -0
  55. package/dist/types/modules/compliance.d.ts.map +1 -0
  56. package/dist/types/modules/index.d.ts +8 -0
  57. package/dist/types/modules/index.d.ts.map +1 -0
  58. package/dist/types/modules/kyc.d.ts +131 -0
  59. package/dist/types/modules/kyc.d.ts.map +1 -0
  60. package/dist/types/modules/token.d.ts +145 -0
  61. package/dist/types/modules/token.d.ts.map +1 -0
  62. package/dist/types/modules/yield.d.ts +143 -0
  63. package/dist/types/modules/yield.d.ts.map +1 -0
  64. package/dist/types/types/index.d.ts +254 -0
  65. package/dist/types/types/index.d.ts.map +1 -0
  66. package/dist/types/utils/index.d.ts +80 -0
  67. package/dist/types/utils/index.d.ts.map +1 -0
  68. package/package.json +52 -0
  69. package/src/client.ts +258 -0
  70. package/src/constants/index.ts +226 -0
  71. package/src/errors/index.ts +291 -0
  72. package/src/index.ts +42 -0
  73. package/src/modules/compliance.ts +252 -0
  74. package/src/modules/index.ts +8 -0
  75. package/src/modules/kyc.ts +446 -0
  76. package/src/modules/token.ts +488 -0
  77. package/src/modules/yield.ts +566 -0
  78. package/src/types/index.ts +326 -0
  79. package/src/utils/index.ts +240 -0
@@ -0,0 +1,326 @@
1
+ /**
2
+ * Core type definitions for the Mantle RWA SDK
3
+ */
4
+
5
+ import type { TransactionReceipt } from 'ethers';
6
+
7
+ /*//////////////////////////////////////////////////////////////
8
+ NETWORK TYPES
9
+ //////////////////////////////////////////////////////////////*/
10
+
11
+ /**
12
+ * Supported network names
13
+ */
14
+ export type NetworkName = 'mantle' | 'mantle-sepolia';
15
+
16
+ /**
17
+ * Custom network configuration
18
+ */
19
+ export interface CustomNetwork {
20
+ rpcUrl: string;
21
+ chainId: number;
22
+ name?: string;
23
+ explorerUrl?: string;
24
+ }
25
+
26
+ /**
27
+ * Network configuration
28
+ */
29
+ export interface NetworkConfig {
30
+ name: string;
31
+ chainId: number;
32
+ rpcUrl: string;
33
+ explorerUrl: string;
34
+ contracts?: {
35
+ factory?: string;
36
+ };
37
+ }
38
+
39
+ /*//////////////////////////////////////////////////////////////
40
+ ACCREDITATION TYPES
41
+ //////////////////////////////////////////////////////////////*/
42
+
43
+ /**
44
+ * Accreditation tiers matching the smart contract enum
45
+ */
46
+ export enum AccreditationTier {
47
+ None = 0,
48
+ Retail = 1,
49
+ Accredited = 2,
50
+ Institutional = 3,
51
+ }
52
+
53
+ /*//////////////////////////////////////////////////////////////
54
+ TRANSACTION TYPES
55
+ //////////////////////////////////////////////////////////////*/
56
+
57
+ /**
58
+ * Parsed event from a transaction
59
+ */
60
+ export interface ParsedEvent {
61
+ name: string;
62
+ args: Record<string, unknown>;
63
+ address: string;
64
+ blockNumber: number;
65
+ transactionHash: string;
66
+ logIndex: number;
67
+ }
68
+
69
+ /**
70
+ * Result of a transaction
71
+ */
72
+ export interface TransactionResult {
73
+ hash: string;
74
+ blockNumber: number;
75
+ gasUsed: bigint;
76
+ status: 'success' | 'failed';
77
+ events: ParsedEvent[];
78
+ receipt: TransactionReceipt;
79
+ }
80
+
81
+ /**
82
+ * Options for transaction execution
83
+ */
84
+ export interface TransactionOptions {
85
+ gasLimit?: bigint;
86
+ maxFeePerGas?: bigint;
87
+ maxPriorityFeePerGas?: bigint;
88
+ nonce?: number;
89
+ retries?: number;
90
+ retryDelay?: number;
91
+ }
92
+
93
+ /*//////////////////////////////////////////////////////////////
94
+ COMPLIANCE TYPES
95
+ //////////////////////////////////////////////////////////////*/
96
+
97
+ /**
98
+ * Available compliance rule types
99
+ */
100
+ export type ComplianceRule =
101
+ | 'accredited-investor'
102
+ | 'transfer-limit-24h'
103
+ | 'transfer-limit-30d'
104
+ | 'holding-period'
105
+ | 'max-investors'
106
+ | 'geographic-restriction';
107
+
108
+ /**
109
+ * Transfer eligibility check result
110
+ */
111
+ export interface TransferEligibility {
112
+ eligible: boolean;
113
+ reason?: string;
114
+ checks: TransferCheck[];
115
+ }
116
+
117
+ /**
118
+ * Individual transfer check result
119
+ */
120
+ export interface TransferCheck {
121
+ name: string;
122
+ passed: boolean;
123
+ details?: string;
124
+ }
125
+
126
+ /*//////////////////////////////////////////////////////////////
127
+ DEPLOYMENT TYPES
128
+ //////////////////////////////////////////////////////////////*/
129
+
130
+ /**
131
+ * Configuration for deploying a new RWA system
132
+ */
133
+ export interface DeploymentConfig {
134
+ tokenName: string;
135
+ tokenSymbol: string;
136
+ initialSupply: string;
137
+ complianceModules?: string[];
138
+ yieldClaimWindowDays?: number;
139
+ vaultSigners: string[];
140
+ vaultThreshold: number;
141
+ vaultWithdrawalThreshold?: string;
142
+ }
143
+
144
+ /**
145
+ * Addresses of deployed contracts
146
+ */
147
+ export interface DeployedContracts {
148
+ token: string;
149
+ vault: string;
150
+ yieldDistributor: string;
151
+ kycRegistry: string;
152
+ }
153
+
154
+ /*//////////////////////////////////////////////////////////////
155
+ TOKEN TYPES
156
+ //////////////////////////////////////////////////////////////*/
157
+
158
+ /**
159
+ * Configuration for deploying a token
160
+ */
161
+ export interface TokenDeployConfig {
162
+ name: string;
163
+ symbol: string;
164
+ totalSupply: string;
165
+ complianceRules?: ComplianceRule[];
166
+ kycRegistryAddress?: string;
167
+ }
168
+
169
+ /**
170
+ * Token information
171
+ */
172
+ export interface TokenInfo {
173
+ address: string;
174
+ name: string;
175
+ symbol: string;
176
+ decimals: number;
177
+ totalSupply: bigint;
178
+ paused: boolean;
179
+ }
180
+
181
+ /*//////////////////////////////////////////////////////////////
182
+ KYC TYPES
183
+ //////////////////////////////////////////////////////////////*/
184
+
185
+ /**
186
+ * Investor data from the KYC registry
187
+ */
188
+ export interface InvestorData {
189
+ verified: boolean;
190
+ tier: AccreditationTier;
191
+ expiry: Date;
192
+ identityHash: string;
193
+ }
194
+
195
+ /**
196
+ * Verification session for KYC flow
197
+ */
198
+ export interface VerificationSession {
199
+ sessionId: string;
200
+ provider: string;
201
+ status: 'pending' | 'in_progress' | 'completed' | 'failed';
202
+ redirectUrl?: string;
203
+ }
204
+
205
+ /**
206
+ * Result of a KYC verification
207
+ */
208
+ export interface VerificationResult {
209
+ verified: boolean;
210
+ tier: AccreditationTier;
211
+ identityHash: string;
212
+ expiryDate: Date;
213
+ rawData?: unknown;
214
+ }
215
+
216
+ /*//////////////////////////////////////////////////////////////
217
+ YIELD TYPES
218
+ //////////////////////////////////////////////////////////////*/
219
+
220
+ /**
221
+ * Configuration for creating a distribution
222
+ */
223
+ export interface DistributionConfig {
224
+ tokenAddress: string;
225
+ paymentToken: string;
226
+ totalAmount: string;
227
+ snapshotDate?: Date;
228
+ claimWindowDays?: number;
229
+ }
230
+
231
+ /**
232
+ * Preview of a distribution
233
+ */
234
+ export interface DistributionPreview {
235
+ totalHolders: number;
236
+ totalSupplyAtSnapshot: bigint;
237
+ distributions: HolderDistribution[];
238
+ }
239
+
240
+ /**
241
+ * Distribution amount for a single holder
242
+ */
243
+ export interface HolderDistribution {
244
+ address: string;
245
+ balance: bigint;
246
+ yieldAmount: bigint;
247
+ percentage: number;
248
+ }
249
+
250
+ /**
251
+ * Distribution information
252
+ */
253
+ export interface Distribution {
254
+ id: number;
255
+ paymentToken: string;
256
+ totalAmount: bigint;
257
+ snapshotId: bigint;
258
+ claimDeadline: Date;
259
+ claimedAmount: bigint;
260
+ }
261
+
262
+ /**
263
+ * Pending claim for an account
264
+ */
265
+ export interface PendingClaim {
266
+ distributionId: number;
267
+ amount: bigint;
268
+ paymentToken: string;
269
+ deadline: Date;
270
+ }
271
+
272
+ /*//////////////////////////////////////////////////////////////
273
+ VAULT TYPES
274
+ //////////////////////////////////////////////////////////////*/
275
+
276
+ /**
277
+ * Withdrawal proposal
278
+ */
279
+ export interface WithdrawalProposal {
280
+ id: number;
281
+ token: string;
282
+ amount: bigint;
283
+ recipient: string;
284
+ approvalCount: number;
285
+ executed: boolean;
286
+ approvers: string[];
287
+ }
288
+
289
+ /**
290
+ * Vault status information
291
+ */
292
+ export interface VaultStatus {
293
+ isEmergency: boolean;
294
+ collateralizationRatio: number;
295
+ backingVerified: boolean;
296
+ }
297
+
298
+ /*//////////////////////////////////////////////////////////////
299
+ COMPLIANCE REPORT TYPES
300
+ //////////////////////////////////////////////////////////////*/
301
+
302
+ /**
303
+ * Compliance report for regulatory purposes
304
+ */
305
+ export interface ComplianceReport {
306
+ generatedAt: Date;
307
+ tokenAddress: string;
308
+ totalHolders: number;
309
+ verifiedHolders: number;
310
+ accreditedHolders: number;
311
+ transfersBlocked: number;
312
+ complianceScore: number;
313
+ }
314
+
315
+ /**
316
+ * Filing data for regulatory submissions
317
+ */
318
+ export interface FilingData {
319
+ filingType: string;
320
+ tokenAddress: string;
321
+ reportingPeriod: {
322
+ start: Date;
323
+ end: Date;
324
+ };
325
+ data: Record<string, unknown>;
326
+ }
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Utility functions for the Mantle RWA SDK
3
+ */
4
+
5
+ import { ethers, type TransactionReceipt, type Interface } from 'ethers';
6
+ import type { ParsedEvent, TransactionResult } from '../types';
7
+ import { NetworkError, ErrorCode, parseNetworkError } from '../errors';
8
+ import { DEFAULTS } from '../constants';
9
+
10
+ /**
11
+ * Validate an Ethereum address
12
+ */
13
+ export function isValidAddress(address: string): boolean {
14
+ try {
15
+ return ethers.isAddress(address);
16
+ } catch {
17
+ return false;
18
+ }
19
+ }
20
+
21
+ /**
22
+ * Validate and normalize an Ethereum address
23
+ */
24
+ export function normalizeAddress(address: string): string {
25
+ if (!isValidAddress(address)) {
26
+ throw new Error(`Invalid address: ${address}`);
27
+ }
28
+ return ethers.getAddress(address);
29
+ }
30
+
31
+ /**
32
+ * Parse a string amount to bigint with decimals
33
+ */
34
+ export function parseAmount(amount: string, decimals: number = 18): bigint {
35
+ return ethers.parseUnits(amount, decimals);
36
+ }
37
+
38
+ /**
39
+ * Format a bigint amount to string with decimals
40
+ */
41
+ export function formatAmount(amount: bigint, decimals: number = 18): string {
42
+ return ethers.formatUnits(amount, decimals);
43
+ }
44
+
45
+ /**
46
+ * Parse events from a transaction receipt
47
+ */
48
+ export function parseEvents(
49
+ receipt: TransactionReceipt,
50
+ contractInterface: Interface
51
+ ): ParsedEvent[] {
52
+ const events: ParsedEvent[] = [];
53
+
54
+ for (const log of receipt.logs) {
55
+ try {
56
+ const parsed = contractInterface.parseLog({
57
+ topics: log.topics as string[],
58
+ data: log.data,
59
+ });
60
+
61
+ if (parsed) {
62
+ const args: Record<string, unknown> = {};
63
+ for (const [key, value] of Object.entries(parsed.args)) {
64
+ // Skip numeric indices
65
+ if (!/^\d+$/.test(key)) {
66
+ args[key] = value;
67
+ }
68
+ }
69
+
70
+ events.push({
71
+ name: parsed.name,
72
+ args,
73
+ address: log.address,
74
+ blockNumber: log.blockNumber,
75
+ transactionHash: log.transactionHash,
76
+ logIndex: log.index,
77
+ });
78
+ }
79
+ } catch {
80
+ // Skip logs that don't match the interface
81
+ }
82
+ }
83
+
84
+ return events;
85
+ }
86
+
87
+ /**
88
+ * Create a transaction result from a receipt
89
+ */
90
+ export function createTransactionResult(
91
+ receipt: TransactionReceipt,
92
+ events: ParsedEvent[]
93
+ ): TransactionResult {
94
+ return {
95
+ hash: receipt.hash,
96
+ blockNumber: receipt.blockNumber,
97
+ gasUsed: receipt.gasUsed,
98
+ status: receipt.status === 1 ? 'success' : 'failed',
99
+ events,
100
+ receipt,
101
+ };
102
+ }
103
+
104
+ /**
105
+ * Sleep for a specified duration
106
+ */
107
+ export function sleep(ms: number): Promise<void> {
108
+ return new Promise((resolve) => setTimeout(resolve, ms));
109
+ }
110
+
111
+ /**
112
+ * Retry a function with exponential backoff
113
+ */
114
+ export async function retry<T>(
115
+ fn: () => Promise<T>,
116
+ options: {
117
+ retries?: number;
118
+ delay?: number;
119
+ onRetry?: (error: unknown, attempt: number) => void;
120
+ } = {}
121
+ ): Promise<T> {
122
+ const { retries = DEFAULTS.TRANSACTION_RETRIES, delay = DEFAULTS.RETRY_DELAY_MS, onRetry } = options;
123
+
124
+ let lastError: unknown;
125
+
126
+ for (let attempt = 0; attempt <= retries; attempt++) {
127
+ try {
128
+ return await fn();
129
+ } catch (error) {
130
+ lastError = error;
131
+
132
+ // Check if error is retryable
133
+ const networkError = parseNetworkError(error);
134
+ if (!networkError.retryable) {
135
+ throw error;
136
+ }
137
+
138
+ if (attempt < retries) {
139
+ onRetry?.(error, attempt + 1);
140
+ await sleep(delay * Math.pow(2, attempt)); // Exponential backoff
141
+ }
142
+ }
143
+ }
144
+
145
+ throw lastError;
146
+ }
147
+
148
+ /**
149
+ * Estimate gas with buffer
150
+ */
151
+ export async function estimateGasWithBuffer(
152
+ estimateFn: () => Promise<bigint>,
153
+ bufferPercent: number = DEFAULTS.GAS_BUFFER_PERCENT
154
+ ): Promise<bigint> {
155
+ const estimate = await estimateFn();
156
+ const buffer = (estimate * BigInt(bufferPercent)) / 100n;
157
+ return estimate + buffer;
158
+ }
159
+
160
+ /**
161
+ * Generate a keccak256 hash of identity data
162
+ */
163
+ export function hashIdentityData(data: {
164
+ firstName?: string;
165
+ lastName?: string;
166
+ dateOfBirth?: string;
167
+ documentNumber?: string;
168
+ country?: string;
169
+ }): string {
170
+ const normalized = JSON.stringify({
171
+ firstName: data.firstName?.toLowerCase().trim(),
172
+ lastName: data.lastName?.toLowerCase().trim(),
173
+ dateOfBirth: data.dateOfBirth,
174
+ documentNumber: data.documentNumber?.toUpperCase().trim(),
175
+ country: data.country?.toUpperCase().trim(),
176
+ });
177
+ return ethers.keccak256(ethers.toUtf8Bytes(normalized));
178
+ }
179
+
180
+ /**
181
+ * Convert a timestamp to a Date object
182
+ */
183
+ export function timestampToDate(timestamp: bigint | number): Date {
184
+ const ts = typeof timestamp === 'bigint' ? Number(timestamp) : timestamp;
185
+ return new Date(ts * 1000);
186
+ }
187
+
188
+ /**
189
+ * Convert a Date to a Unix timestamp
190
+ */
191
+ export function dateToTimestamp(date: Date): number {
192
+ return Math.floor(date.getTime() / 1000);
193
+ }
194
+
195
+ /**
196
+ * Check if a timestamp is expired
197
+ */
198
+ export function isExpired(timestamp: bigint | number): boolean {
199
+ const now = Math.floor(Date.now() / 1000);
200
+ const ts = typeof timestamp === 'bigint' ? Number(timestamp) : timestamp;
201
+ return ts < now;
202
+ }
203
+
204
+ /**
205
+ * Calculate percentage
206
+ */
207
+ export function calculatePercentage(part: bigint, total: bigint): number {
208
+ if (total === 0n) return 0;
209
+ return Number((part * 10000n) / total) / 100;
210
+ }
211
+
212
+ /**
213
+ * Chunk an array into smaller arrays
214
+ */
215
+ export function chunk<T>(array: T[], size: number): T[][] {
216
+ const chunks: T[][] = [];
217
+ for (let i = 0; i < array.length; i += size) {
218
+ chunks.push(array.slice(i, i + size));
219
+ }
220
+ return chunks;
221
+ }
222
+
223
+ /**
224
+ * Wait for a transaction to be mined
225
+ */
226
+ export async function waitForTransaction(
227
+ provider: ethers.Provider,
228
+ hash: string,
229
+ confirmations: number = 1
230
+ ): Promise<TransactionReceipt> {
231
+ const receipt = await provider.waitForTransaction(hash, confirmations);
232
+ if (!receipt) {
233
+ throw new NetworkError(
234
+ ErrorCode.TIMEOUT,
235
+ `Transaction ${hash} was not mined`,
236
+ true
237
+ );
238
+ }
239
+ return receipt;
240
+ }