rwa-tokenized-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.
- package/README.md +741 -0
- package/dist/client/rwa.d.ts +280 -0
- package/dist/client/rwa.d.ts.map +1 -0
- package/dist/client/rwa.js +708 -0
- package/dist/client/rwa.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +130 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +80 -0
package/README.md
ADDED
|
@@ -0,0 +1,741 @@
|
|
|
1
|
+
# RWA Tokenized SDK
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/rwa-tokenized-sdk)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
|
|
7
|
+
A comprehensive TypeScript/React SDK for integrating **Mantle Network**-based payments, subscriptions, and RWA (Real World Assets) tokenization into your applications. This SDK provides a complete interface to interact with RWA Factory and Property smart contracts, enabling seamless tokenization of real-world assets.
|
|
8
|
+
|
|
9
|
+
## ✨ Features
|
|
10
|
+
|
|
11
|
+
- 🏗️ **Complete RWA Operations** - Launch, manage, and query tokenized properties
|
|
12
|
+
- 💰 **ERC1155 Token Support** - Full token transfer, approval, and batch operations
|
|
13
|
+
- 🔐 **Ownership Management** - Factory and property ownership controls
|
|
14
|
+
- 📊 **Comprehensive Queries** - Get properties, balances, approvals, and more
|
|
15
|
+
- ⚡ **Type-Safe** - Full TypeScript support with comprehensive type definitions
|
|
16
|
+
- 🔌 **Provider Agnostic** - Works with ethers.js v5 and v6
|
|
17
|
+
- 🌐 **Mantle Network** - Optimized for Mantle Network (EVM-compatible)
|
|
18
|
+
|
|
19
|
+
## 📋 Table of Contents
|
|
20
|
+
|
|
21
|
+
- [Installation](#installation)
|
|
22
|
+
- [Quick Start](#quick-start)
|
|
23
|
+
- [Mantle Network Configuration](#mantle-network-configuration)
|
|
24
|
+
- [RWA Launchpad API](#rwa-launchpad-api)
|
|
25
|
+
- [Complete Examples](#complete-examples)
|
|
26
|
+
- [API Reference](#api-reference)
|
|
27
|
+
- [Types](#types)
|
|
28
|
+
- [Troubleshooting](#troubleshooting)
|
|
29
|
+
- [Contributing](#contributing)
|
|
30
|
+
- [License](#license)
|
|
31
|
+
|
|
32
|
+
## 📦 Installation
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install rwa-tokenized-sdk
|
|
36
|
+
# or
|
|
37
|
+
yarn add rwa-tokenized-sdk
|
|
38
|
+
# or
|
|
39
|
+
pnpm add rwa-tokenized-sdk
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Peer Dependencies
|
|
43
|
+
|
|
44
|
+
This SDK requires the following peer dependencies:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install ethers@^6.0.0
|
|
48
|
+
# For React components (optional)
|
|
49
|
+
npm install react@^18.0.0 react-markdown@^10.0.0 lucide-react@^0.500.0
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 🚀 Quick Start
|
|
53
|
+
|
|
54
|
+
### Basic Setup
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { createRWAClient } from 'rwa-tokenized-sdk'
|
|
58
|
+
import { ethers } from 'ethers'
|
|
59
|
+
|
|
60
|
+
// Connect to Mantle Network
|
|
61
|
+
const provider = new ethers.JsonRpcProvider('https://rpc.mantle.xyz')
|
|
62
|
+
const signer = await provider.getSigner()
|
|
63
|
+
|
|
64
|
+
// Create RWA client
|
|
65
|
+
const rwa = createRWAClient({
|
|
66
|
+
factoryAddress: '0x7d7aF5715e5671e0E3126b2428Dc2629bD9061e3'
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
// Get all properties
|
|
70
|
+
const properties = await rwa.getAllProperties(provider)
|
|
71
|
+
console.log(`Found ${properties.length} properties`)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Launch a Property
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { createRWAClient } from 'rwa-tokenized-sdk'
|
|
78
|
+
import { ethers } from 'ethers'
|
|
79
|
+
|
|
80
|
+
async function launchProperty() {
|
|
81
|
+
const provider = new ethers.BrowserProvider(window.ethereum)
|
|
82
|
+
const signer = await provider.getSigner()
|
|
83
|
+
|
|
84
|
+
const rwa = createRWAClient({
|
|
85
|
+
factoryAddress: '0x7d7aF5715e5671e0E3126b2428Dc2629bD9061e3'
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
const result = await rwa.launchProperty({
|
|
90
|
+
assetName: 'Downtown Office Building',
|
|
91
|
+
assetType: 'Real Estate',
|
|
92
|
+
description: 'A premium office building in downtown',
|
|
93
|
+
isOwner: true,
|
|
94
|
+
approximatedValue: BigInt('1000000000000000000000'), // $1000 in wei
|
|
95
|
+
totalSupply: BigInt('1000000'), // 1M tokens
|
|
96
|
+
propertyAddress: '123 Main St, City, State',
|
|
97
|
+
squareMeters: BigInt('500'),
|
|
98
|
+
uri: 'ipfs://QmYourMetadataHashHere'
|
|
99
|
+
}, signer)
|
|
100
|
+
|
|
101
|
+
console.log('✅ Property launched!')
|
|
102
|
+
console.log('Property Address:', result.propertyAddress)
|
|
103
|
+
console.log('Transaction Hash:', result.transactionHash)
|
|
104
|
+
console.log('Property ID:', result.propertyId)
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.error('❌ Failed to launch property:', error)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## 🌐 Mantle Network Configuration
|
|
112
|
+
|
|
113
|
+
### Network Details
|
|
114
|
+
|
|
115
|
+
| Network | Chain ID | RPC URL | Explorer |
|
|
116
|
+
|---------|----------|---------|----------|
|
|
117
|
+
| Mantle Mainnet | 5000 | `https://rpc.mantle.xyz` | [explorer.mantle.xyz](https://explorer.mantle.xyz) |
|
|
118
|
+
| Mantle Testnet | 5001 | `https://rpc.testnet.mantle.xyz` | [explorer.testnet.mantle.xyz](https://explorer.testnet.mantle.xyz) |
|
|
119
|
+
|
|
120
|
+
### Connecting to Mantle Network
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { ethers } from 'ethers'
|
|
124
|
+
|
|
125
|
+
// Option 1: Using public RPC
|
|
126
|
+
const provider = new ethers.JsonRpcProvider('https://rpc.mantle.xyz')
|
|
127
|
+
|
|
128
|
+
// Option 2: Using browser provider (MetaMask, etc.)
|
|
129
|
+
const provider = new ethers.BrowserProvider(window.ethereum)
|
|
130
|
+
|
|
131
|
+
// Option 3: Using custom RPC
|
|
132
|
+
const provider = new ethers.JsonRpcProvider('YOUR_CUSTOM_RPC_URL', {
|
|
133
|
+
name: 'Mantle',
|
|
134
|
+
chainId: 5000
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
// Get signer
|
|
138
|
+
const signer = await provider.getSigner()
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Adding Mantle to MetaMask
|
|
142
|
+
|
|
143
|
+
Users can add Mantle Network to MetaMask with these details:
|
|
144
|
+
|
|
145
|
+
**Mainnet:**
|
|
146
|
+
- Network Name: Mantle
|
|
147
|
+
- RPC URL: `https://rpc.mantle.xyz`
|
|
148
|
+
- Chain ID: `5000`
|
|
149
|
+
- Currency Symbol: `MNT`
|
|
150
|
+
- Block Explorer: `https://explorer.mantle.xyz`
|
|
151
|
+
|
|
152
|
+
**Testnet:**
|
|
153
|
+
- Network Name: Mantle Testnet
|
|
154
|
+
- RPC URL: `https://rpc.testnet.mantle.xyz`
|
|
155
|
+
- Chain ID: `5001`
|
|
156
|
+
- Currency Symbol: `MNT`
|
|
157
|
+
- Block Explorer: `https://explorer.testnet.mantle.xyz`
|
|
158
|
+
|
|
159
|
+
## 🏗️ RWA Launchpad API
|
|
160
|
+
|
|
161
|
+
### Creating a Client
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
import { createRWAClient, createDefaultRWAClient } from 'rwa-tokenized-sdk'
|
|
165
|
+
|
|
166
|
+
// Custom factory address
|
|
167
|
+
const rwa = createRWAClient({
|
|
168
|
+
factoryAddress: '0x7d7aF5715e5671e0E3126b2428Dc2629bD9061e3',
|
|
169
|
+
chainId: 5000, // Optional
|
|
170
|
+
rpcUrl: 'https://rpc.mantle.xyz' // Optional
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
// Using default factory address
|
|
174
|
+
const rwa = createDefaultRWAClient({
|
|
175
|
+
chainId: 5000 // Optional override
|
|
176
|
+
})
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Factory Operations
|
|
180
|
+
|
|
181
|
+
#### Launch Property
|
|
182
|
+
|
|
183
|
+
Create a new tokenized property.
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
const result = await rwa.launchProperty({
|
|
187
|
+
assetName: 'Luxury Apartment Complex',
|
|
188
|
+
assetType: 'Real Estate',
|
|
189
|
+
description: 'Modern apartment complex with 50 units',
|
|
190
|
+
isOwner: true,
|
|
191
|
+
approximatedValue: BigInt('5000000000000000000000'), // $5000
|
|
192
|
+
totalSupply: BigInt('10000000'), // 10M tokens
|
|
193
|
+
propertyAddress: '456 Oak Avenue, City',
|
|
194
|
+
squareMeters: BigInt('2000'),
|
|
195
|
+
uri: 'ipfs://QmYourMetadataHash'
|
|
196
|
+
}, signer)
|
|
197
|
+
|
|
198
|
+
// Returns: { transactionHash, propertyAddress, propertyId }
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
#### Query Properties
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
// Get all property addresses
|
|
205
|
+
const allProperties = await rwa.getAllProperties(provider)
|
|
206
|
+
|
|
207
|
+
// Get total count
|
|
208
|
+
const count = await rwa.getPropertyCount(provider)
|
|
209
|
+
|
|
210
|
+
// Get property by index
|
|
211
|
+
const property = await rwa.getProperty(0, provider)
|
|
212
|
+
|
|
213
|
+
// Get property information
|
|
214
|
+
const info = await rwa.getPropertyInfo(propertyAddress, provider)
|
|
215
|
+
|
|
216
|
+
// Get user's properties
|
|
217
|
+
const userProperties = await rwa.getUserProperties(userAddress, provider)
|
|
218
|
+
|
|
219
|
+
// Get user property by index
|
|
220
|
+
const userProperty = await rwa.getUserPropertyByIndex(userAddress, 0, provider)
|
|
221
|
+
|
|
222
|
+
// Validate property address
|
|
223
|
+
const isValid = await rwa.isValidProperty(propertyAddress, provider)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### Factory Ownership
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
// Get factory owner
|
|
230
|
+
const owner = await rwa.getFactoryOwner(provider)
|
|
231
|
+
|
|
232
|
+
// Transfer ownership (only owner)
|
|
233
|
+
await rwa.transferFactoryOwnership(newOwnerAddress, signer)
|
|
234
|
+
|
|
235
|
+
// Renounce ownership (only owner)
|
|
236
|
+
await rwa.renounceFactoryOwnership(signer)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Property Operations
|
|
240
|
+
|
|
241
|
+
#### Get Property Details
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
// Get complete property details with URI
|
|
245
|
+
const details = await rwa.getPropertyDetails(propertyAddress, provider)
|
|
246
|
+
|
|
247
|
+
console.log(details)
|
|
248
|
+
// {
|
|
249
|
+
// assetName: 'Downtown Office Building',
|
|
250
|
+
// assetType: 'Real Estate',
|
|
251
|
+
// description: '...',
|
|
252
|
+
// isOwner: true,
|
|
253
|
+
// approximatedValue: '1000000000000',
|
|
254
|
+
// totalSupply: '1000000',
|
|
255
|
+
// propertyAddress: '123 Main St',
|
|
256
|
+
// squareMeters: '500',
|
|
257
|
+
// contractAddress: '0x...',
|
|
258
|
+
// uri: 'ipfs://Qm...'
|
|
259
|
+
// }
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
#### Token Balance Operations
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
// Get single balance
|
|
266
|
+
const balance = await rwa.getTokenBalance(
|
|
267
|
+
propertyAddress,
|
|
268
|
+
userAddress,
|
|
269
|
+
provider
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
// Get batch balances (multiple accounts/tokens)
|
|
273
|
+
const balances = await rwa.getBatchTokenBalances(
|
|
274
|
+
propertyAddress,
|
|
275
|
+
['0x...', '0x...'], // accounts
|
|
276
|
+
[1, 1], // tokenIds
|
|
277
|
+
provider
|
|
278
|
+
)
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
#### Token Transfers
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
// Single token transfer
|
|
285
|
+
const txHash = await rwa.transferTokens(
|
|
286
|
+
propertyAddress,
|
|
287
|
+
fromAddress,
|
|
288
|
+
toAddress,
|
|
289
|
+
1, // PROPERTY_TOKEN_ID
|
|
290
|
+
BigInt('1000'), // amount
|
|
291
|
+
signer,
|
|
292
|
+
'0x' // optional data
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
// Batch token transfer
|
|
296
|
+
const batchTxHash = await rwa.batchTransferTokens(
|
|
297
|
+
propertyAddress,
|
|
298
|
+
fromAddress,
|
|
299
|
+
toAddress,
|
|
300
|
+
[1, 1], // tokenIds
|
|
301
|
+
[BigInt('100'), BigInt('200')], // amounts
|
|
302
|
+
signer
|
|
303
|
+
)
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
#### Operator Approvals
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
// Approve operator for all tokens
|
|
310
|
+
await rwa.setApprovalForAll(
|
|
311
|
+
propertyAddress,
|
|
312
|
+
operatorAddress,
|
|
313
|
+
true, // approve
|
|
314
|
+
signer
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
// Revoke operator approval
|
|
318
|
+
await rwa.setApprovalForAll(
|
|
319
|
+
propertyAddress,
|
|
320
|
+
operatorAddress,
|
|
321
|
+
false, // revoke
|
|
322
|
+
signer
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
// Check if operator is approved
|
|
326
|
+
const isApproved = await rwa.isApprovedForAll(
|
|
327
|
+
propertyAddress,
|
|
328
|
+
accountAddress,
|
|
329
|
+
operatorAddress,
|
|
330
|
+
provider
|
|
331
|
+
)
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
#### Property Ownership
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
// Get property owner
|
|
338
|
+
const owner = await rwa.getPropertyOwner(propertyAddress, provider)
|
|
339
|
+
|
|
340
|
+
// Transfer property ownership
|
|
341
|
+
await rwa.transferPropertyOwnership(
|
|
342
|
+
propertyAddress,
|
|
343
|
+
newOwnerAddress,
|
|
344
|
+
signer
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
// Renounce property ownership
|
|
348
|
+
await rwa.renouncePropertyOwnership(propertyAddress, signer)
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
#### Interface Support
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
// Check if contract supports an interface (ERC165)
|
|
355
|
+
const supportsERC1155 = await rwa.supportsInterface(
|
|
356
|
+
propertyAddress,
|
|
357
|
+
'0xd9b67a26', // ERC1155 interface ID
|
|
358
|
+
provider
|
|
359
|
+
)
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## 📚 Complete Examples
|
|
363
|
+
|
|
364
|
+
### Example 1: Complete Property Lifecycle
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
import { createRWAClient } from 'rwa-tokenized-sdk'
|
|
368
|
+
import { ethers } from 'ethers'
|
|
369
|
+
|
|
370
|
+
async function completePropertyLifecycle() {
|
|
371
|
+
try {
|
|
372
|
+
// 1. Setup
|
|
373
|
+
const provider = new ethers.BrowserProvider(window.ethereum)
|
|
374
|
+
const signer = await provider.getSigner()
|
|
375
|
+
const userAddress = await signer.getAddress()
|
|
376
|
+
|
|
377
|
+
const rwa = createRWAClient({
|
|
378
|
+
factoryAddress: '0x7d7aF5715e5671e0E3126b2428Dc2629bD9061e3'
|
|
379
|
+
})
|
|
380
|
+
|
|
381
|
+
// 2. Launch property
|
|
382
|
+
console.log('🚀 Launching property...')
|
|
383
|
+
const launchResult = await rwa.launchProperty({
|
|
384
|
+
assetName: 'Downtown Office Building',
|
|
385
|
+
assetType: 'Real Estate',
|
|
386
|
+
description: 'A premium office building',
|
|
387
|
+
isOwner: true,
|
|
388
|
+
approximatedValue: BigInt('1000000000000000000000'),
|
|
389
|
+
totalSupply: BigInt('1000000'),
|
|
390
|
+
propertyAddress: '123 Main St',
|
|
391
|
+
squareMeters: BigInt('500'),
|
|
392
|
+
uri: 'ipfs://QmYourHash'
|
|
393
|
+
}, signer)
|
|
394
|
+
|
|
395
|
+
const propertyAddress = launchResult.propertyAddress
|
|
396
|
+
console.log('✅ Property launched:', propertyAddress)
|
|
397
|
+
|
|
398
|
+
// 3. Get property details
|
|
399
|
+
const details = await rwa.getPropertyDetails(propertyAddress, provider)
|
|
400
|
+
console.log('📋 Property details:', details)
|
|
401
|
+
|
|
402
|
+
// 4. Check token balance
|
|
403
|
+
const balance = await rwa.getTokenBalance(
|
|
404
|
+
propertyAddress,
|
|
405
|
+
userAddress,
|
|
406
|
+
provider
|
|
407
|
+
)
|
|
408
|
+
console.log('💰 Your balance:', balance.toString())
|
|
409
|
+
|
|
410
|
+
// 5. Transfer tokens
|
|
411
|
+
const recipient = '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'
|
|
412
|
+
console.log('📤 Transferring tokens...')
|
|
413
|
+
const transferTx = await rwa.transferTokens(
|
|
414
|
+
propertyAddress,
|
|
415
|
+
userAddress,
|
|
416
|
+
recipient,
|
|
417
|
+
1,
|
|
418
|
+
BigInt('100'),
|
|
419
|
+
signer
|
|
420
|
+
)
|
|
421
|
+
console.log('✅ Transfer complete:', transferTx)
|
|
422
|
+
|
|
423
|
+
// 6. Approve operator
|
|
424
|
+
const operator = '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'
|
|
425
|
+
console.log('🔐 Approving operator...')
|
|
426
|
+
await rwa.setApprovalForAll(propertyAddress, operator, true, signer)
|
|
427
|
+
|
|
428
|
+
// 7. Verify approval
|
|
429
|
+
const isApproved = await rwa.isApprovedForAll(
|
|
430
|
+
propertyAddress,
|
|
431
|
+
userAddress,
|
|
432
|
+
operator,
|
|
433
|
+
provider
|
|
434
|
+
)
|
|
435
|
+
console.log('✅ Operator approved:', isApproved)
|
|
436
|
+
|
|
437
|
+
// 8. Get user properties
|
|
438
|
+
const userProperties = await rwa.getUserProperties(userAddress, provider)
|
|
439
|
+
console.log('📦 Your properties:', userProperties)
|
|
440
|
+
|
|
441
|
+
} catch (error) {
|
|
442
|
+
console.error('❌ Error:', error)
|
|
443
|
+
throw error
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Example 2: Marketplace Integration
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
import { createRWAClient } from 'rwa-tokenized-sdk'
|
|
452
|
+
import { ethers } from 'ethers'
|
|
453
|
+
|
|
454
|
+
async function marketplaceExample() {
|
|
455
|
+
const provider = new ethers.JsonRpcProvider('https://rpc.mantle.xyz')
|
|
456
|
+
const rwa = createRWAClient({
|
|
457
|
+
factoryAddress: '0x7d7aF5715e5671e0E3126b2428Dc2629bD9061e3'
|
|
458
|
+
})
|
|
459
|
+
|
|
460
|
+
// Get all properties
|
|
461
|
+
const properties = await rwa.getAllProperties(provider)
|
|
462
|
+
|
|
463
|
+
// Get details for each property
|
|
464
|
+
const propertyDetails = await Promise.all(
|
|
465
|
+
properties.map(async (address) => {
|
|
466
|
+
try {
|
|
467
|
+
const details = await rwa.getPropertyDetails(address, provider)
|
|
468
|
+
const balance = await rwa.getTokenBalance(
|
|
469
|
+
address,
|
|
470
|
+
'0xYourAddress',
|
|
471
|
+
provider
|
|
472
|
+
)
|
|
473
|
+
return {
|
|
474
|
+
...details,
|
|
475
|
+
userBalance: balance.toString()
|
|
476
|
+
}
|
|
477
|
+
} catch (error) {
|
|
478
|
+
console.error(`Error fetching ${address}:`, error)
|
|
479
|
+
return null
|
|
480
|
+
}
|
|
481
|
+
})
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
// Filter out nulls and display
|
|
485
|
+
const validProperties = propertyDetails.filter(p => p !== null)
|
|
486
|
+
console.log('Available properties:', validProperties)
|
|
487
|
+
|
|
488
|
+
return validProperties
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### Example 3: Batch Operations
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
import { createRWAClient } from 'rwa-tokenized-sdk'
|
|
496
|
+
import { ethers } from 'ethers'
|
|
497
|
+
|
|
498
|
+
async function batchOperationsExample() {
|
|
499
|
+
const provider = new ethers.JsonRpcProvider('https://rpc.mantle.xyz')
|
|
500
|
+
const signer = await provider.getSigner()
|
|
501
|
+
const rwa = createRWAClient({
|
|
502
|
+
factoryAddress: '0x7d7aF5715e5671e0E3126b2428Dc2629bD9061e3'
|
|
503
|
+
})
|
|
504
|
+
|
|
505
|
+
const propertyAddress = '0x...'
|
|
506
|
+
const accounts = [
|
|
507
|
+
'0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
|
|
508
|
+
'0x8ba1f109551bD432803012645Hac136c22C9'
|
|
509
|
+
]
|
|
510
|
+
|
|
511
|
+
// Get batch balances
|
|
512
|
+
const balances = await rwa.getBatchTokenBalances(
|
|
513
|
+
propertyAddress,
|
|
514
|
+
accounts,
|
|
515
|
+
[1, 1], // PROPERTY_TOKEN_ID for both
|
|
516
|
+
provider
|
|
517
|
+
)
|
|
518
|
+
|
|
519
|
+
console.log('Balances:', balances.map(b => b.toString()))
|
|
520
|
+
|
|
521
|
+
// Batch transfer
|
|
522
|
+
const txHash = await rwa.batchTransferTokens(
|
|
523
|
+
propertyAddress,
|
|
524
|
+
await signer.getAddress(),
|
|
525
|
+
'0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
|
|
526
|
+
[1, 1],
|
|
527
|
+
[BigInt('100'), BigInt('200')],
|
|
528
|
+
signer
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
console.log('Batch transfer complete:', txHash)
|
|
532
|
+
}
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
## 📖 API Reference
|
|
536
|
+
|
|
537
|
+
### `createRWAClient(config)`
|
|
538
|
+
|
|
539
|
+
Creates an RWA client instance.
|
|
540
|
+
|
|
541
|
+
**Parameters:**
|
|
542
|
+
- `config.factoryAddress` (string, required) - Factory contract address
|
|
543
|
+
- `config.chainId` (number, optional) - Chain ID
|
|
544
|
+
- `config.rpcUrl` (string, optional) - RPC URL
|
|
545
|
+
|
|
546
|
+
**Returns:** RWA client object
|
|
547
|
+
|
|
548
|
+
### Factory Methods
|
|
549
|
+
|
|
550
|
+
| Method | Description | Returns |
|
|
551
|
+
|--------|-------------|---------|
|
|
552
|
+
| `launchProperty(params, signer)` | Launch a new property | `LaunchPropertyResult` |
|
|
553
|
+
| `getAllProperties(provider)` | Get all property addresses | `string[]` |
|
|
554
|
+
| `getPropertyCount(provider)` | Get total property count | `bigint` |
|
|
555
|
+
| `getProperty(index, provider)` | Get property by index | `string` |
|
|
556
|
+
| `getPropertyInfo(address, provider)` | Get property info | `ParsedRWAPropertyInfo` |
|
|
557
|
+
| `getUserProperties(user, provider)` | Get user's properties | `string[]` |
|
|
558
|
+
| `getUserPropertyCount(user, provider)` | Get user's property count | `bigint` |
|
|
559
|
+
| `getUserPropertyByIndex(user, index, provider)` | Get user property by index | `string` |
|
|
560
|
+
| `isValidProperty(address, provider)` | Validate property address | `boolean` |
|
|
561
|
+
| `getFactoryOwner(provider)` | Get factory owner | `string` |
|
|
562
|
+
| `transferFactoryOwnership(newOwner, signer)` | Transfer factory ownership | `string` (tx hash) |
|
|
563
|
+
| `renounceFactoryOwnership(signer)` | Renounce factory ownership | `string` (tx hash) |
|
|
564
|
+
|
|
565
|
+
### Property Methods
|
|
566
|
+
|
|
567
|
+
| Method | Description | Returns |
|
|
568
|
+
|--------|-------------|---------|
|
|
569
|
+
| `getPropertyDetails(address, provider)` | Get complete property details | `ParsedRWAPropertyInfo` |
|
|
570
|
+
| `getTokenBalance(address, user, provider)` | Get token balance | `bigint` |
|
|
571
|
+
| `getBatchTokenBalances(address, accounts, tokenIds, provider)` | Get batch balances | `bigint[]` |
|
|
572
|
+
| `transferTokens(address, from, to, tokenId, amount, signer, data?)` | Transfer tokens | `string` (tx hash) |
|
|
573
|
+
| `batchTransferTokens(address, from, to, tokenIds, amounts, signer, data?)` | Batch transfer | `string` (tx hash) |
|
|
574
|
+
| `setApprovalForAll(address, operator, approved, signer)` | Approve/revoke operator | `string` (tx hash) |
|
|
575
|
+
| `isApprovedForAll(address, account, operator, provider)` | Check approval | `boolean` |
|
|
576
|
+
| `supportsInterface(address, interfaceId, provider)` | Check interface support | `boolean` |
|
|
577
|
+
| `getPropertyOwner(address, provider)` | Get property owner | `string` |
|
|
578
|
+
| `transferPropertyOwnership(address, newOwner, signer)` | Transfer ownership | `string` (tx hash) |
|
|
579
|
+
| `renouncePropertyOwnership(address, signer)` | Renounce ownership | `string` (tx hash) |
|
|
580
|
+
|
|
581
|
+
## 🔧 Types
|
|
582
|
+
|
|
583
|
+
All TypeScript types are exported for your convenience:
|
|
584
|
+
|
|
585
|
+
```typescript
|
|
586
|
+
import type {
|
|
587
|
+
// RWA Types
|
|
588
|
+
RWAPropertyInfo,
|
|
589
|
+
ParsedRWAPropertyInfo,
|
|
590
|
+
LaunchPropertyParams,
|
|
591
|
+
RWASDKConfig,
|
|
592
|
+
LaunchPropertyResult,
|
|
593
|
+
RWAPropertyMetadata,
|
|
594
|
+
|
|
595
|
+
// Payment/Subscription Types
|
|
596
|
+
CheckoutOptions,
|
|
597
|
+
VerifyResponse,
|
|
598
|
+
SubscriptionStatusData,
|
|
599
|
+
Plan,
|
|
600
|
+
Subscription,
|
|
601
|
+
AccessResponse
|
|
602
|
+
} from 'rwa-tokenized-sdk'
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
### Type Definitions
|
|
606
|
+
|
|
607
|
+
```typescript
|
|
608
|
+
interface LaunchPropertyParams {
|
|
609
|
+
assetName: string
|
|
610
|
+
assetType: string
|
|
611
|
+
description: string
|
|
612
|
+
isOwner: boolean
|
|
613
|
+
approximatedValue: bigint | string
|
|
614
|
+
totalSupply: bigint | string
|
|
615
|
+
propertyAddress: string
|
|
616
|
+
squareMeters: bigint | string
|
|
617
|
+
uri: string
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
interface ParsedRWAPropertyInfo {
|
|
621
|
+
assetName: string
|
|
622
|
+
assetType: string
|
|
623
|
+
description: string
|
|
624
|
+
isOwner: boolean
|
|
625
|
+
approximatedValue: string
|
|
626
|
+
totalSupply: string
|
|
627
|
+
propertyAddress: string
|
|
628
|
+
squareMeters: string
|
|
629
|
+
contractAddress?: string
|
|
630
|
+
uri?: string
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
interface LaunchPropertyResult {
|
|
634
|
+
transactionHash: string
|
|
635
|
+
propertyAddress: string
|
|
636
|
+
propertyId: number
|
|
637
|
+
}
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
## 🐛 Troubleshooting
|
|
641
|
+
|
|
642
|
+
### Common Issues
|
|
643
|
+
|
|
644
|
+
#### 1. "Factory address is required" Error
|
|
645
|
+
|
|
646
|
+
**Solution:** Make sure you provide a factory address when creating the client:
|
|
647
|
+
|
|
648
|
+
```typescript
|
|
649
|
+
const rwa = createRWAClient({
|
|
650
|
+
factoryAddress: '0x7d7aF5715e5671e0E3126b2428Dc2629bD9061e3' // Required!
|
|
651
|
+
})
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
#### 2. Transaction Reverted
|
|
655
|
+
|
|
656
|
+
**Possible causes:**
|
|
657
|
+
- Insufficient gas
|
|
658
|
+
- Invalid parameters
|
|
659
|
+
- Insufficient balance
|
|
660
|
+
- Not authorized (for ownership functions)
|
|
661
|
+
|
|
662
|
+
**Solution:**
|
|
663
|
+
```typescript
|
|
664
|
+
try {
|
|
665
|
+
const tx = await rwa.launchProperty(params, signer)
|
|
666
|
+
// Wait for confirmation
|
|
667
|
+
await tx.wait()
|
|
668
|
+
} catch (error) {
|
|
669
|
+
if (error.reason) {
|
|
670
|
+
console.error('Transaction failed:', error.reason)
|
|
671
|
+
}
|
|
672
|
+
// Check error.code for specific error types
|
|
673
|
+
}
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
#### 3. Provider Not Connected
|
|
677
|
+
|
|
678
|
+
**Solution:**
|
|
679
|
+
```typescript
|
|
680
|
+
// Check if provider is available
|
|
681
|
+
if (!window.ethereum) {
|
|
682
|
+
throw new Error('Please install MetaMask or another wallet')
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
const provider = new ethers.BrowserProvider(window.ethereum)
|
|
686
|
+
await provider.send('eth_requestAccounts', [])
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
#### 4. Wrong Network
|
|
690
|
+
|
|
691
|
+
**Solution:**
|
|
692
|
+
```typescript
|
|
693
|
+
// Check current network
|
|
694
|
+
const network = await provider.getNetwork()
|
|
695
|
+
if (network.chainId !== 5000n) { // Mantle Mainnet
|
|
696
|
+
// Prompt user to switch network
|
|
697
|
+
await window.ethereum.request({
|
|
698
|
+
method: 'wallet_switchEthereumChain',
|
|
699
|
+
params: [{ chainId: '0x1388' }] // 5000 in hex
|
|
700
|
+
})
|
|
701
|
+
}
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
#### 5. Type Errors with ethers.js
|
|
705
|
+
|
|
706
|
+
**Solution:** Make sure you're using ethers.js v6:
|
|
707
|
+
|
|
708
|
+
```bash
|
|
709
|
+
npm install ethers@^6.0.0
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
For ethers.js v5 compatibility, the SDK handles both versions automatically.
|
|
713
|
+
|
|
714
|
+
## 🛠️ Building
|
|
715
|
+
|
|
716
|
+
```bash
|
|
717
|
+
cd sdk
|
|
718
|
+
npm install
|
|
719
|
+
npm run build
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
Outputs to `dist/` with TypeScript declarations.
|
|
723
|
+
|
|
724
|
+
## 🤝 Contributing
|
|
725
|
+
|
|
726
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
727
|
+
|
|
728
|
+
## 📄 License
|
|
729
|
+
|
|
730
|
+
MIT
|
|
731
|
+
|
|
732
|
+
## 🔗 Links
|
|
733
|
+
|
|
734
|
+
- [Mantle Network](https://www.mantle.xyz/)
|
|
735
|
+
- [Mantle Explorer](https://explorer.mantle.xyz/)
|
|
736
|
+
- [Documentation](https://docs.mantle.xyz/)
|
|
737
|
+
- [GitHub Repository](https://github.com/adityajha2005/synq)
|
|
738
|
+
|
|
739
|
+
---
|
|
740
|
+
|
|
741
|
+
Made with ❤️ for the Mantle Network ecosystem
|