@monadns/sdk 2.0.0 → 2.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 +121 -14
- package/dist/index.cjs +76 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -10
- package/dist/index.d.ts +63 -10
- package/dist/index.js +72 -6
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +146 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +55 -1
- package/dist/react.d.ts +55 -1
- package/dist/react.js +144 -1
- package/dist/react.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -92,6 +92,34 @@ function Twitter({ name }: { name: string }) {
|
|
|
92
92
|
}
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
### Check ownership and expiry
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
import { useMNSOwner, useMNSExpiry } from '@monadns/sdk/react';
|
|
99
|
+
|
|
100
|
+
function NameInfo({ name }: { name: string }) {
|
|
101
|
+
const { owner, loading: ownerLoading } = useMNSOwner(name);
|
|
102
|
+
const {
|
|
103
|
+
daysUntilExpiry,
|
|
104
|
+
isExpired,
|
|
105
|
+
loading: expiryLoading,
|
|
106
|
+
} = useMNSExpiry(name);
|
|
107
|
+
|
|
108
|
+
if (ownerLoading || expiryLoading) return <div>Loading...</div>;
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<div>
|
|
112
|
+
<p>Owner: {owner}</p>
|
|
113
|
+
{isExpired ? (
|
|
114
|
+
<p className="text-red-500">This name has expired!</p>
|
|
115
|
+
) : (
|
|
116
|
+
<p>Expires in {daysUntilExpiry} days</p>
|
|
117
|
+
)}
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
95
123
|
## Registration (with wagmi)
|
|
96
124
|
|
|
97
125
|
The SDK returns transaction parameters that work directly with wagmi's `useWriteContract`:
|
|
@@ -275,6 +303,43 @@ function ProfileEditor({ name }: { name: string }) {
|
|
|
275
303
|
}
|
|
276
304
|
```
|
|
277
305
|
|
|
306
|
+
## Advanced Usage
|
|
307
|
+
|
|
308
|
+
### Check Name Ownership & Expiry
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { getOwner, getExpiry, getResolver } from '@monadns/sdk';
|
|
312
|
+
|
|
313
|
+
// Check who owns a name
|
|
314
|
+
const owner = await getOwner('alice.mon');
|
|
315
|
+
console.log('Owner:', owner);
|
|
316
|
+
|
|
317
|
+
// Check when it expires
|
|
318
|
+
const expiry = await getExpiry('alice.mon');
|
|
319
|
+
const expiryDate = new Date(expiry * 1000);
|
|
320
|
+
const daysLeft = Math.floor(
|
|
321
|
+
(expiry * 1000 - Date.now()) / (1000 * 60 * 60 * 24),
|
|
322
|
+
);
|
|
323
|
+
console.log(`Expires: ${expiryDate.toLocaleDateString()} (${daysLeft} days)`);
|
|
324
|
+
|
|
325
|
+
// Get resolver contract
|
|
326
|
+
const resolver = await getResolver('alice.mon');
|
|
327
|
+
console.log('Resolver:', resolver);
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Check Availability Before Registration
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
import { getAvailable } from '@monadns/sdk';
|
|
334
|
+
|
|
335
|
+
const available = await getAvailable('alice.mon');
|
|
336
|
+
if (available) {
|
|
337
|
+
console.log('alice.mon is available for registration!');
|
|
338
|
+
} else {
|
|
339
|
+
console.log('alice.mon is already taken');
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
278
343
|
## API Reference
|
|
279
344
|
|
|
280
345
|
### Core Functions (`@monadns/sdk`)
|
|
@@ -287,7 +352,10 @@ function ProfileEditor({ name }: { name: string }) {
|
|
|
287
352
|
| `resolveInput(input)` | Accepts name or address, returns address |
|
|
288
353
|
| `getTextRecord(name, key)` | Get text record (avatar, url, etc.) |
|
|
289
354
|
| `getAvatarUrl(name)` | Get resolved avatar URL (handles IPFS, NFTs) |
|
|
290
|
-
| `
|
|
355
|
+
| `getAvailable(name)` | Check if a name is available for registration |
|
|
356
|
+
| `getOwner(name)` | Get the owner address of a name |
|
|
357
|
+
| `getResolver(name)` | Get the resolver contract address |
|
|
358
|
+
| `getExpiry(name)` | Get expiry timestamp (Unix seconds) |
|
|
291
359
|
| `clearCache()` | Clear the resolution cache |
|
|
292
360
|
| `getRegistrationInfo(label, address)` | Get price, availability, freebie status |
|
|
293
361
|
| `getRegisterTx(label, address)` | Get tx params for registration |
|
|
@@ -296,18 +364,21 @@ function ProfileEditor({ name }: { name: string }) {
|
|
|
296
364
|
|
|
297
365
|
### React Hooks (`@monadns/sdk/react`)
|
|
298
366
|
|
|
299
|
-
| Hook | Returns
|
|
300
|
-
| ------------------------------------- |
|
|
301
|
-
| `useMNSName(address)` | `{ name, loading, error }`
|
|
302
|
-
| `useMNSAddress(name)` | `{ address, loading, error }`
|
|
303
|
-
| `useMNSDisplay(address)` | `{ displayName, monName, loading }`
|
|
304
|
-
| `useMNSResolve()` | `{ resolve, address, name, loading, error }`
|
|
305
|
-
| `useMNSText(name, key)` | `{ value, loading, error }`
|
|
306
|
-
| `useMNSAvatar(name)` | `{ url, loading, error }`
|
|
307
|
-
| `
|
|
308
|
-
| `
|
|
309
|
-
| `
|
|
310
|
-
| `
|
|
367
|
+
| Hook | Returns | Description |
|
|
368
|
+
| ------------------------------------- | -------------------------------------------------------------------- | ----------------------------- |
|
|
369
|
+
| `useMNSName(address)` | `{ name, loading, error }` | Reverse resolution |
|
|
370
|
+
| `useMNSAddress(name)` | `{ address, loading, error }` | Forward resolution |
|
|
371
|
+
| `useMNSDisplay(address)` | `{ displayName, monName, loading }` | Display-ready name |
|
|
372
|
+
| `useMNSResolve()` | `{ resolve, address, name, loading, error }` | On-demand resolver for inputs |
|
|
373
|
+
| `useMNSText(name, key)` | `{ value, loading, error }` | Read text records |
|
|
374
|
+
| `useMNSAvatar(name)` | `{ url, loading, error }` | Resolved avatar URL |
|
|
375
|
+
| `useMNSOwner(name)` | `{ owner, loading, error }` | Get name owner |
|
|
376
|
+
| `useMNSResolver(name)` | `{ resolver, loading, error }` | Get resolver address |
|
|
377
|
+
| `useMNSExpiry(name)` | `{ expiry, expiryDate, daysUntilExpiry, isExpired, loading, error }` | Get expiration info |
|
|
378
|
+
| `useRegistrationInfo(label, address)` | `{ info, loading, error }` | Pre-registration data |
|
|
379
|
+
| `useMNSRegister()` | `{ prepare, tx, loading, error }` | Prepare registration tx |
|
|
380
|
+
| `useMNSTextRecords()` | `{ setAvatar, setTwitter, ... }` | Prepare text record txs |
|
|
381
|
+
| `useMNSAddr()` | `{ setAddr }` | Prepare address update tx |
|
|
311
382
|
|
|
312
383
|
### Custom RPC
|
|
313
384
|
|
|
@@ -341,6 +412,42 @@ const name = await lookupAddress('0x...', { client });
|
|
|
341
412
|
|
|
342
413
|
**Chain:** Monad Mainnet (Chain ID 143)
|
|
343
414
|
|
|
415
|
+
## Migrating from v2.0 to v2.1
|
|
416
|
+
|
|
417
|
+
### Breaking Changes
|
|
418
|
+
|
|
419
|
+
**`isRegistered()` has been renamed to `getAvailable()` with inverted logic**
|
|
420
|
+
|
|
421
|
+
**Before (v2.0):**
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
const registered = await isRegistered('alice.mon');
|
|
425
|
+
if (registered) {
|
|
426
|
+
console.log('Name is taken');
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
**After (v2.1):**
|
|
431
|
+
|
|
432
|
+
```typescript
|
|
433
|
+
const available = await getAvailable('alice.mon');
|
|
434
|
+
if (available) {
|
|
435
|
+
console.log('Name is available for registration');
|
|
436
|
+
} else {
|
|
437
|
+
console.log('Name is taken');
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### New Features
|
|
442
|
+
|
|
443
|
+
- `getOwner(name)` - Get the owner of a name
|
|
444
|
+
- `getResolver(name)` - Get the resolver contract
|
|
445
|
+
- `getExpiry(name)` - Get expiration timestamp
|
|
446
|
+
- `useMNSOwner(name)` - React hook for ownership info
|
|
447
|
+
- `useMNSResolver(name)` - React hook for resolver info
|
|
448
|
+
- `useMNSExpiry(name)` - React hook for expiry info with computed fields
|
|
449
|
+
- `MNS_BASE_REGISTRAR` constant now exported
|
|
450
|
+
|
|
344
451
|
## Compatibility
|
|
345
452
|
|
|
346
453
|
- **Frameworks:** React 17+, Next.js (App Router & Pages), Remix, Vite, CRA
|
|
@@ -350,4 +457,4 @@ const name = await lookupAddress('0x...', { client });
|
|
|
350
457
|
|
|
351
458
|
## License
|
|
352
459
|
|
|
353
|
-
[Unlicense](https://unlicense.org)
|
|
460
|
+
[Unlicense](https://unlicense.org) – public domain, no attribution required.
|
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
|
+
MNS_BASE_REGISTRAR: () => MNS_BASE_REGISTRAR,
|
|
23
24
|
MNS_CONTROLLER: () => MNS_CONTROLLER,
|
|
24
25
|
MNS_PUBLIC_RESOLVER: () => MNS_PUBLIC_RESOLVER,
|
|
25
26
|
MNS_REGISTRY: () => MNS_REGISTRY,
|
|
@@ -27,15 +28,18 @@ __export(src_exports, {
|
|
|
27
28
|
clearCache: () => clearCache,
|
|
28
29
|
controllerReadAbi: () => controllerReadAbi,
|
|
29
30
|
controllerWriteAbi: () => controllerWriteAbi,
|
|
31
|
+
getAvailable: () => getAvailable,
|
|
30
32
|
getAvatarUrl: () => getAvatarUrl,
|
|
31
33
|
getDisplayName: () => getDisplayName,
|
|
34
|
+
getExpiry: () => getExpiry,
|
|
32
35
|
getMNSClient: () => getMNSClient,
|
|
36
|
+
getOwner: () => getOwner,
|
|
33
37
|
getRegisterTx: () => getRegisterTx,
|
|
34
38
|
getRegistrationInfo: () => getRegistrationInfo,
|
|
39
|
+
getResolver: () => getResolver,
|
|
35
40
|
getSetAddrTx: () => getSetAddrTx,
|
|
36
41
|
getSetTextTx: () => getSetTextTx,
|
|
37
42
|
getTextRecord: () => getTextRecord,
|
|
38
|
-
isRegistered: () => isRegistered,
|
|
39
43
|
lookupAddress: () => lookupAddress,
|
|
40
44
|
resolveInput: () => resolveInput,
|
|
41
45
|
resolveName: () => resolveName,
|
|
@@ -71,6 +75,7 @@ function getMNSClient(config) {
|
|
|
71
75
|
var MNS_REGISTRY = "0x13f963486e741c8d3fcdc0a34a910920339a19ce";
|
|
72
76
|
var MNS_PUBLIC_RESOLVER = "0xa2eb94c88e55d944aced2066c5cec9b759801f97";
|
|
73
77
|
var MNS_CONTROLLER = "0x98866c55adbc73ec6c272bb3604ddbdee3f282a8";
|
|
78
|
+
var MNS_BASE_REGISTRAR = "0x104a49db9318c284d462841b6940bdb46624ca55";
|
|
74
79
|
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
75
80
|
var registryAbi = [
|
|
76
81
|
{
|
|
@@ -79,6 +84,13 @@ var registryAbi = [
|
|
|
79
84
|
inputs: [{ name: "node", type: "bytes32" }],
|
|
80
85
|
outputs: [{ name: "", type: "address" }],
|
|
81
86
|
stateMutability: "view"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "owner",
|
|
90
|
+
type: "function",
|
|
91
|
+
inputs: [{ name: "node", type: "bytes32" }],
|
|
92
|
+
outputs: [{ name: "", type: "address" }],
|
|
93
|
+
stateMutability: "view"
|
|
82
94
|
}
|
|
83
95
|
];
|
|
84
96
|
var resolverAbi = [
|
|
@@ -203,6 +215,64 @@ async function getTextRecord(name, key, config) {
|
|
|
203
215
|
return null;
|
|
204
216
|
}
|
|
205
217
|
}
|
|
218
|
+
async function getOwner(name, config) {
|
|
219
|
+
try {
|
|
220
|
+
const client = getMNSClient(config);
|
|
221
|
+
const node = (0, import_viem2.namehash)(name.toLowerCase());
|
|
222
|
+
const owner = await client.readContract({
|
|
223
|
+
address: MNS_REGISTRY,
|
|
224
|
+
abi: registryAbi,
|
|
225
|
+
functionName: "owner",
|
|
226
|
+
args: [node]
|
|
227
|
+
});
|
|
228
|
+
return owner === ZERO_ADDRESS ? null : owner;
|
|
229
|
+
} catch {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
async function getResolver(name, config) {
|
|
234
|
+
try {
|
|
235
|
+
const client = getMNSClient(config);
|
|
236
|
+
const node = (0, import_viem2.namehash)(name.toLowerCase());
|
|
237
|
+
const resolver = await client.readContract({
|
|
238
|
+
address: MNS_REGISTRY,
|
|
239
|
+
abi: registryAbi,
|
|
240
|
+
functionName: "resolver",
|
|
241
|
+
args: [node]
|
|
242
|
+
});
|
|
243
|
+
return resolver === ZERO_ADDRESS ? null : resolver;
|
|
244
|
+
} catch {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
async function getExpiry(name, config) {
|
|
249
|
+
try {
|
|
250
|
+
const client = getMNSClient(config);
|
|
251
|
+
const label = name.replace(".mon", "");
|
|
252
|
+
const labelHash = (0, import_viem2.keccak256)((0, import_viem2.toBytes)(label));
|
|
253
|
+
const expiry = await client.readContract({
|
|
254
|
+
address: MNS_BASE_REGISTRAR,
|
|
255
|
+
abi: [
|
|
256
|
+
{
|
|
257
|
+
name: "nameExpires",
|
|
258
|
+
type: "function",
|
|
259
|
+
inputs: [{ name: "id", type: "uint256" }],
|
|
260
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
261
|
+
stateMutability: "view"
|
|
262
|
+
}
|
|
263
|
+
],
|
|
264
|
+
functionName: "nameExpires",
|
|
265
|
+
args: [BigInt(labelHash)]
|
|
266
|
+
});
|
|
267
|
+
return Number(expiry);
|
|
268
|
+
} catch {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
async function getAvailable(name, config) {
|
|
273
|
+
const addr = await resolveName(name, config);
|
|
274
|
+
return addr === null;
|
|
275
|
+
}
|
|
206
276
|
async function getDisplayName(address, config) {
|
|
207
277
|
const name = await lookupAddress(address, config);
|
|
208
278
|
if (name) return name;
|
|
@@ -215,10 +285,6 @@ async function resolveInput(input, config) {
|
|
|
215
285
|
if (trimmed.endsWith(".mon")) return resolveName(trimmed, config);
|
|
216
286
|
return resolveName(`${trimmed}.mon`, config);
|
|
217
287
|
}
|
|
218
|
-
async function isRegistered(name, config) {
|
|
219
|
-
const addr = await resolveName(name, config);
|
|
220
|
-
return addr !== null;
|
|
221
|
-
}
|
|
222
288
|
async function getAvatarUrl(name, config) {
|
|
223
289
|
const raw = await getTextRecord(name, "avatar", config);
|
|
224
290
|
if (!raw) return null;
|
|
@@ -427,6 +493,7 @@ var TEXT_RECORD_KEYS = {
|
|
|
427
493
|
};
|
|
428
494
|
// Annotate the CommonJS export names for ESM import in node:
|
|
429
495
|
0 && (module.exports = {
|
|
496
|
+
MNS_BASE_REGISTRAR,
|
|
430
497
|
MNS_CONTROLLER,
|
|
431
498
|
MNS_PUBLIC_RESOLVER,
|
|
432
499
|
MNS_REGISTRY,
|
|
@@ -434,15 +501,18 @@ var TEXT_RECORD_KEYS = {
|
|
|
434
501
|
clearCache,
|
|
435
502
|
controllerReadAbi,
|
|
436
503
|
controllerWriteAbi,
|
|
504
|
+
getAvailable,
|
|
437
505
|
getAvatarUrl,
|
|
438
506
|
getDisplayName,
|
|
507
|
+
getExpiry,
|
|
439
508
|
getMNSClient,
|
|
509
|
+
getOwner,
|
|
440
510
|
getRegisterTx,
|
|
441
511
|
getRegistrationInfo,
|
|
512
|
+
getResolver,
|
|
442
513
|
getSetAddrTx,
|
|
443
514
|
getSetTextTx,
|
|
444
515
|
getTextRecord,
|
|
445
|
-
isRegistered,
|
|
446
516
|
lookupAddress,
|
|
447
517
|
resolveInput,
|
|
448
518
|
resolveName,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/resolve.ts","../src/client.ts","../src/constants.ts","../src/write.ts"],"sourcesContent":["// Core resolution (read-only)\nexport {\n resolveName,\n lookupAddress,\n getTextRecord,\n getAvatarUrl,\n getDisplayName,\n resolveInput,\n isRegistered,\n clearCache,\n} from './resolve';\n\n// Write helpers\nexport {\n getRegistrationInfo,\n getRegisterTx,\n getSetTextTx,\n getSetAddrTx,\n TEXT_RECORD_KEYS,\n controllerReadAbi,\n controllerWriteAbi,\n resolverWriteAbi,\n} from './write';\nexport type { RegistrationInfo } from './write';\n\n// Client config\nexport { getMNSClient } from './client';\nexport type { MNSClientConfig } from './client';\n\n// Constants\nexport { MNS_REGISTRY, MNS_PUBLIC_RESOLVER, MNS_CONTROLLER } from './constants';\n","import { namehash } from 'viem';\nimport { getMNSClient, type MNSClientConfig } from './client';\nimport {\n MNS_REGISTRY,\n ZERO_ADDRESS,\n registryAbi,\n resolverAbi,\n} from './constants';\n\n// ─── Cache ─────────────────────────────────────────────────────\n\nconst nameCache = new Map<string, { value: string | null; ts: number }>();\nconst addrCache = new Map<string, { value: string | null; ts: number }>();\n\nconst CACHE_TTL = 60_000; // 1 minute\n\nfunction getCached(\n cache: Map<string, { value: string | null; ts: number }>,\n key: string,\n) {\n const entry = cache.get(key);\n if (entry && Date.now() - entry.ts < CACHE_TTL) return entry.value;\n return undefined;\n}\n\n// ─── Forward Resolution ────────────────────────────────────────\n\n/**\n * Resolve a .mon name to an address.\n *\n * @param name - Full name including .mon (e.g. \"alice.mon\")\n * @param config - Optional client configuration\n * @returns The resolved address, or null if not found\n *\n * @example\n * ```ts\n * import { resolveName } from '@monadns/sdk'\n *\n * const address = await resolveName('alice.mon')\n * // '0xa05a8BF1eda5bbC2b3aCAF03D04f77bD7d66Cc47'\n * ```\n */\nexport async function resolveName(\n name: string,\n config?: MNSClientConfig,\n): Promise<string | null> {\n const key = name.toLowerCase();\n const cached = getCached(addrCache, key);\n if (cached !== undefined) return cached;\n\n try {\n const client = getMNSClient(config);\n const node = namehash(key) as `0x${string}`;\n\n const resolver = await client.readContract({\n address: MNS_REGISTRY,\n abi: registryAbi,\n functionName: 'resolver',\n args: [node],\n });\n\n if (resolver === ZERO_ADDRESS) {\n addrCache.set(key, { value: null, ts: Date.now() });\n return null;\n }\n\n const addr = await client.readContract({\n address: resolver,\n abi: resolverAbi,\n functionName: 'addr',\n args: [node],\n });\n\n const result = addr === ZERO_ADDRESS ? null : addr;\n addrCache.set(key, { value: result, ts: Date.now() });\n return result;\n } catch {\n addrCache.set(key, { value: null, ts: Date.now() });\n return null;\n }\n}\n\n// ─── Reverse Resolution ────────────────────────────────────────\n\n/**\n * Look up the primary .mon name for an address.\n *\n * @param address - A 0x-prefixed Monad address\n * @param config - Optional client configuration\n * @returns The primary name (e.g. \"alice.mon\"), or null\n *\n * @example\n * ```ts\n * import { lookupAddress } from '@monadns/sdk'\n *\n * const name = await lookupAddress('0xa05a8BF1...')\n * // 'alice.mon'\n * ```\n */\nexport async function lookupAddress(\n address: string,\n config?: MNSClientConfig,\n): Promise<string | null> {\n const key = address.toLowerCase();\n const cached = getCached(nameCache, key);\n if (cached !== undefined) return cached;\n\n try {\n const client = getMNSClient(config);\n const reverseNode = namehash(\n `${key.slice(2)}.addr.reverse`,\n ) as `0x${string}`;\n\n const resolver = await client.readContract({\n address: MNS_REGISTRY,\n abi: registryAbi,\n functionName: 'resolver',\n args: [reverseNode],\n });\n\n if (resolver === ZERO_ADDRESS) {\n nameCache.set(key, { value: null, ts: Date.now() });\n return null;\n }\n\n const name = await client.readContract({\n address: resolver,\n abi: resolverAbi,\n functionName: 'name',\n args: [reverseNode],\n });\n\n const result = name || null;\n nameCache.set(key, { value: result, ts: Date.now() });\n return result;\n } catch {\n nameCache.set(key, { value: null, ts: Date.now() });\n return null;\n }\n}\n\n// ─── Text Records ──────────────────────────────────────────────\n\n/**\n * Get a text record for a .mon name.\n *\n * @param name - Full name including .mon\n * @param key - The text record key (e.g. \"avatar\", \"url\", \"com.twitter\")\n * @param config - Optional client configuration\n *\n * @example\n * ```ts\n * const avatar = await getTextRecord('alice.mon', 'avatar')\n * const twitter = await getTextRecord('alice.mon', 'com.twitter')\n * ```\n */\nexport async function getTextRecord(\n name: string,\n key: string,\n config?: MNSClientConfig,\n): Promise<string | null> {\n try {\n const client = getMNSClient(config);\n const node = namehash(name.toLowerCase()) as `0x${string}`;\n\n const resolver = await client.readContract({\n address: MNS_REGISTRY,\n abi: registryAbi,\n functionName: 'resolver',\n args: [node],\n });\n\n if (resolver === ZERO_ADDRESS) return null;\n\n const value = await client.readContract({\n address: resolver,\n abi: resolverAbi,\n functionName: 'text',\n args: [node, key],\n });\n\n return value || null;\n } catch {\n return null;\n }\n}\n\n// ─── Helpers ───────────────────────────────────────────────────\n\n/**\n * Get a display-friendly name for an address.\n * Returns the .mon name if set, otherwise a truncated address.\n *\n * @example\n * ```ts\n * const display = await getDisplayName('0xa05a8BF1...')\n * // 'alice.mon' or '0xa05a...Cc47'\n * ```\n */\nexport async function getDisplayName(\n address: string,\n config?: MNSClientConfig,\n): Promise<string> {\n const name = await lookupAddress(address, config);\n if (name) return name;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\n/**\n * Smart resolver — accepts either a .mon name or a raw address.\n * Useful for input fields where users can type either.\n *\n * @returns The resolved address, or null if invalid/not found\n *\n * @example\n * ```ts\n * const addr = await resolveInput('alice.mon') // resolves name\n * const addr = await resolveInput('alice') // tries alice.mon\n * const addr = await resolveInput('0xa05a...') // passes through\n * ```\n */\nexport async function resolveInput(\n input: string,\n config?: MNSClientConfig,\n): Promise<string | null> {\n const trimmed = input.trim();\n if (!trimmed) return null;\n\n if (trimmed.startsWith('0x') && trimmed.length === 42) return trimmed;\n if (trimmed.endsWith('.mon')) return resolveName(trimmed, config);\n\n // Try appending .mon\n return resolveName(`${trimmed}.mon`, config);\n}\n\n/**\n * Check if a .mon name is registered.\n *\n * @example\n * ```ts\n * const taken = await isRegistered('alice.mon')\n * ```\n */\nexport async function isRegistered(\n name: string,\n config?: MNSClientConfig,\n): Promise<boolean> {\n const addr = await resolveName(name, config);\n return addr !== null;\n}\n\n/**\n * Get a resolved avatar URL for a .mon name.\n *\n * Handles multiple avatar formats:\n * - Direct HTTPS URLs: returned as-is\n * - IPFS URIs (ipfs://...): resolved via public gateway\n * - NFT references (eip155:chainId/erc721:contract/tokenId): fetches tokenURI and extracts image\n *\n * @param name - Full name including .mon\n * @param config - Optional client configuration\n * @returns A usable HTTPS URL, or null\n *\n * @example\n * ```ts\n * const avatarUrl = await getAvatarUrl('alice.mon')\n * // 'https://example.com/avatar.png'\n * ```\n */\nexport async function getAvatarUrl(\n name: string,\n config?: MNSClientConfig,\n): Promise<string | null> {\n const raw = await getTextRecord(name, 'avatar', config);\n if (!raw) return null;\n\n // Direct HTTP(S) URL\n if (raw.startsWith('http://') || raw.startsWith('https://')) {\n return raw;\n }\n\n // IPFS\n if (raw.startsWith('ipfs://')) {\n const hash = raw.slice(7);\n return `https://ipfs.io/ipfs/${hash}`;\n }\n\n // NFT reference: eip155:{chainId}/erc721:{contract}/{tokenId}\n // or eip155:{chainId}/erc1155:{contract}/{tokenId}\n const nftMatch = raw.match(\n /^eip155:(\\d+)\\/(erc721|erc1155):0x([a-fA-F0-9]{40})\\/(\\d+)$/,\n );\n if (nftMatch) {\n try {\n const client = getMNSClient(config);\n const contract = `0x${nftMatch[3]}` as `0x${string}`;\n const tokenId = BigInt(nftMatch[4]);\n\n const tokenUriAbi = [\n {\n name: nftMatch[2] === 'erc721' ? 'tokenURI' : 'uri',\n type: 'function',\n inputs: [{ name: 'tokenId', type: 'uint256' }],\n outputs: [{ name: '', type: 'string' }],\n stateMutability: 'view',\n },\n ] as const;\n\n let tokenUri = (await client.readContract({\n address: contract,\n abi: tokenUriAbi,\n functionName: nftMatch[2] === 'erc721' ? 'tokenURI' : 'uri',\n args: [tokenId],\n })) as string;\n\n // Resolve IPFS tokenURI\n if (tokenUri.startsWith('ipfs://')) {\n tokenUri = `https://ipfs.io/ipfs/${tokenUri.slice(7)}`;\n }\n\n // Fetch metadata JSON and extract image\n const res = await fetch(tokenUri);\n const metadata = await res.json();\n let image = metadata.image || metadata.image_url || null;\n\n if (image && image.startsWith('ipfs://')) {\n image = `https://ipfs.io/ipfs/${image.slice(7)}`;\n }\n\n return image;\n } catch {\n return null;\n }\n }\n\n // data: URIs\n if (raw.startsWith('data:')) {\n return raw;\n }\n\n return null;\n}\n\n/**\n * Clear the internal resolution cache.\n * Useful after a new registration.\n */\nexport function clearCache() {\n nameCache.clear();\n addrCache.clear();\n}\n","import {\n createPublicClient,\n http,\n type PublicClient,\n type Chain,\n type Transport,\n} from 'viem';\nimport { monad } from 'viem/chains';\n\nexport type MNSClientConfig = {\n /** Custom RPC URL. Defaults to the public Monad RPC. */\n rpcUrl?: string;\n /** Existing viem PublicClient to reuse instead of creating a new one. */\n client?: PublicClient<Transport, Chain>;\n};\n\nlet defaultClient: PublicClient<Transport, Chain> | null = null;\n\n/**\n * Get or create the MNS public client.\n * Reuses a singleton by default; pass config to override.\n */\nexport function getMNSClient(\n config?: MNSClientConfig,\n): PublicClient<Transport, Chain> {\n if (config?.client) return config.client;\n\n if (config?.rpcUrl) {\n return createPublicClient({\n chain: monad,\n transport: http(config.rpcUrl),\n });\n }\n\n if (!defaultClient) {\n defaultClient = createPublicClient({\n chain: monad,\n transport: http(),\n });\n }\n\n return defaultClient;\n}\n","export const MNS_REGISTRY =\n '0x13f963486e741c8d3fcdc0a34a910920339a19ce' as const;\nexport const MNS_PUBLIC_RESOLVER =\n '0xa2eb94c88e55d944aced2066c5cec9b759801f97' as const;\nexport const MNS_CONTROLLER =\n '0x98866c55adbc73ec6c272bb3604ddbdee3f282a8' as const;\n\nexport const ZERO_ADDRESS =\n '0x0000000000000000000000000000000000000000' as const;\n\nexport const registryAbi = [\n {\n name: 'resolver',\n type: 'function',\n inputs: [{ name: 'node', type: 'bytes32' }],\n outputs: [{ name: '', type: 'address' }],\n stateMutability: 'view',\n },\n] as const;\n\nexport const resolverAbi = [\n {\n name: 'addr',\n type: 'function',\n inputs: [{ name: 'node', type: 'bytes32' }],\n outputs: [{ name: '', type: 'address' }],\n stateMutability: 'view',\n },\n {\n name: 'name',\n type: 'function',\n inputs: [{ name: 'node', type: 'bytes32' }],\n outputs: [{ name: '', type: 'string' }],\n stateMutability: 'view',\n },\n {\n name: 'text',\n type: 'function',\n inputs: [\n { name: 'node', type: 'bytes32' },\n { name: 'key', type: 'string' },\n ],\n outputs: [{ name: '', type: 'string' }],\n stateMutability: 'view',\n },\n] as const;\n","import { namehash } from 'viem';\nimport { getMNSClient, type MNSClientConfig } from './client';\nimport { MNS_CONTROLLER, MNS_PUBLIC_RESOLVER } from './constants';\n\n/**\n * MNS Write Helpers\n *\n * These return transaction parameters ({ address, abi, functionName, args, value })\n * that you pass to wagmi's writeContract or any wallet client.\n * The user signs with their own wallet.\n */\n\n// ─── ABIs ──────────────────────────────────────────────────────\n\nexport const controllerReadAbi = [\n {\n name: 'available',\n type: 'function',\n inputs: [{ name: 'label', type: 'string' }],\n outputs: [{ name: '', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n name: 'rentPrice',\n type: 'function',\n inputs: [\n { name: 'label', type: 'string' },\n { name: 'duration', type: 'uint256' },\n ],\n outputs: [{ name: '', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n name: 'hasClaimedFreebie',\n type: 'function',\n inputs: [{ name: 'user', type: 'address' }],\n outputs: [{ name: '', type: 'bool' }],\n stateMutability: 'view',\n },\n] as const;\n\nexport const controllerWriteAbi = [\n {\n name: 'register',\n type: 'function',\n inputs: [\n { name: 'label', type: 'string' },\n { name: 'owner', type: 'address' },\n { name: 'duration', type: 'uint256' },\n ],\n outputs: [{ name: '', type: 'uint256' }],\n stateMutability: 'payable',\n },\n] as const;\n\nexport const resolverWriteAbi = [\n {\n name: 'setText',\n type: 'function',\n inputs: [\n { name: 'node', type: 'bytes32' },\n { name: 'key', type: 'string' },\n { name: 'value', type: 'string' },\n ],\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n name: 'setAddr',\n type: 'function',\n inputs: [\n { name: 'node', type: 'bytes32' },\n { name: 'a', type: 'address' },\n ],\n outputs: [],\n stateMutability: 'nonpayable',\n },\n] as const;\n\n// ─── Types ─────────────────────────────────────────────────────\n\nexport type RegistrationInfo = {\n available: boolean;\n price: bigint;\n isFreebie: boolean;\n hasClaimed: boolean;\n duration: bigint;\n label: string;\n};\n\n// ─── Registration ──────────────────────────────────────────────\n\nconst ONE_YEAR = BigInt(365 * 24 * 60 * 60);\n\n/**\n * Get all info needed before registration.\n *\n * @example\n * ```ts\n * const info = await getRegistrationInfo('alice', userAddress)\n * // { available: true, price: 96831564n..., isFreebie: true, ... }\n * ```\n */\nexport async function getRegistrationInfo(\n label: string,\n userAddress: string,\n durationYears = 1,\n config?: MNSClientConfig,\n): Promise<RegistrationInfo> {\n const client = getMNSClient(config);\n const duration = ONE_YEAR * BigInt(durationYears);\n\n const [available, price, hasClaimed, balance] = await Promise.all([\n client.readContract({\n address: MNS_CONTROLLER,\n abi: controllerReadAbi,\n functionName: 'available',\n args: [label],\n }),\n client.readContract({\n address: MNS_CONTROLLER,\n abi: controllerReadAbi,\n functionName: 'rentPrice',\n args: [label, duration],\n }),\n client.readContract({\n address: MNS_CONTROLLER,\n abi: controllerReadAbi,\n functionName: 'hasClaimedFreebie',\n args: [userAddress as `0x${string}`],\n }),\n client.getBalance({ address: userAddress as `0x${string}` }),\n ]);\n\n const isFreebie = balance >= 10n * 10n ** 18n && !hasClaimed;\n\n return { available, price, isFreebie, hasClaimed, duration, label };\n}\n\n/**\n * Get transaction parameters for registering a .mon name.\n * Pass the result to wagmi's writeContract.\n *\n * @example\n * ```ts\n * const tx = await getRegisterTx('alice', userAddress)\n * writeContract(tx)\n * ```\n */\nexport async function getRegisterTx(\n label: string,\n ownerAddress: string,\n durationYears = 1,\n config?: MNSClientConfig,\n) {\n const info = await getRegistrationInfo(\n label,\n ownerAddress,\n durationYears,\n config,\n );\n\n if (!info.available) {\n throw new Error(`${label}.mon is not available`);\n }\n\n return {\n address: MNS_CONTROLLER,\n abi: controllerWriteAbi,\n functionName: 'register' as const,\n args: [label, ownerAddress as `0x${string}`, info.duration] as const,\n value: info.isFreebie ? 0n : info.price,\n gas: 3_000_000n,\n _meta: {\n label,\n isFreebie: info.isFreebie,\n price: info.price,\n duration: info.duration,\n },\n };\n}\n\n// ─── Text Records ──────────────────────────────────────────────\n\n/**\n * Get transaction parameters for setting a text record.\n * The connected user must own the name.\n *\n * @example\n * ```ts\n * const tx = getSetTextTx('alice.mon', 'avatar', 'https://example.com/pic.png')\n * writeContract(tx)\n * ```\n */\nexport function getSetTextTx(name: string, key: string, value: string) {\n const node = namehash(\n name.endsWith('.mon') ? name : `${name}.mon`,\n ) as `0x${string}`;\n\n return {\n address: MNS_PUBLIC_RESOLVER,\n abi: resolverWriteAbi,\n functionName: 'setText' as const,\n args: [node, key, value] as const,\n };\n}\n\n/**\n * Get transaction parameters for setting the address record.\n */\nexport function getSetAddrTx(name: string, addr: string) {\n const node = namehash(\n name.endsWith('.mon') ? name : `${name}.mon`,\n ) as `0x${string}`;\n\n return {\n address: MNS_PUBLIC_RESOLVER,\n abi: resolverWriteAbi,\n functionName: 'setAddr' as const,\n args: [node, addr as `0x${string}`] as const,\n };\n}\n\nexport const TEXT_RECORD_KEYS = {\n avatar: 'avatar',\n url: 'url',\n description: 'description',\n email: 'email',\n twitter: 'com.twitter',\n github: 'com.github',\n discord: 'com.discord',\n telegram: 'org.telegram',\n} as const;\n"],"mappings":"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","names":["import_viem","import_viem"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/resolve.ts","../src/client.ts","../src/constants.ts","../src/write.ts"],"sourcesContent":["// Core resolution (read-only)\nexport {\n resolveName,\n lookupAddress,\n getTextRecord,\n getAvatarUrl,\n getDisplayName,\n resolveInput,\n getAvailable,\n getOwner,\n getResolver,\n getExpiry,\n clearCache,\n} from './resolve';\n\n// Write helpers\nexport {\n getRegistrationInfo,\n getRegisterTx,\n getSetTextTx,\n getSetAddrTx,\n TEXT_RECORD_KEYS,\n controllerReadAbi,\n controllerWriteAbi,\n resolverWriteAbi,\n} from './write';\nexport type { RegistrationInfo } from './write';\n\n// Client config\nexport { getMNSClient } from './client';\nexport type { MNSClientConfig } from './client';\n\n// Constants\nexport {\n MNS_REGISTRY,\n MNS_PUBLIC_RESOLVER,\n MNS_CONTROLLER,\n MNS_BASE_REGISTRAR,\n} from './constants';\n","import { namehash, keccak256, toBytes } from 'viem';\nimport { getMNSClient, type MNSClientConfig } from './client';\nimport {\n MNS_REGISTRY,\n MNS_BASE_REGISTRAR,\n ZERO_ADDRESS,\n registryAbi,\n resolverAbi,\n} from './constants';\n\n// ─── Cache ─────────────────────────────────────────────────────\n\nconst nameCache = new Map<string, { value: string | null; ts: number }>();\nconst addrCache = new Map<string, { value: string | null; ts: number }>();\n\nconst CACHE_TTL = 60_000; // 1 minute\n\nfunction getCached(\n cache: Map<string, { value: string | null; ts: number }>,\n key: string,\n) {\n const entry = cache.get(key);\n if (entry && Date.now() - entry.ts < CACHE_TTL) return entry.value;\n return undefined;\n}\n\n// ─── Forward Resolution ────────────────────────────────────────\n\n/**\n * Resolve a .mon name to an address.\n *\n * @param name - Full name including .mon (e.g. \"alice.mon\")\n * @param config - Optional client configuration\n * @returns The resolved address, or null if not found\n *\n * @example\n * ```ts\n * import { resolveName } from '@monadns/sdk'\n *\n * const address = await resolveName('alice.mon')\n * // '0xa05a8BF1eda5bbC2b3aCAF03D04f77bD7d66Cc47'\n * ```\n */\nexport async function resolveName(\n name: string,\n config?: MNSClientConfig,\n): Promise<string | null> {\n const key = name.toLowerCase();\n const cached = getCached(addrCache, key);\n if (cached !== undefined) return cached;\n\n try {\n const client = getMNSClient(config);\n const node = namehash(key) as `0x${string}`;\n\n const resolver = await client.readContract({\n address: MNS_REGISTRY,\n abi: registryAbi,\n functionName: 'resolver',\n args: [node],\n });\n\n if (resolver === ZERO_ADDRESS) {\n addrCache.set(key, { value: null, ts: Date.now() });\n return null;\n }\n\n const addr = await client.readContract({\n address: resolver,\n abi: resolverAbi,\n functionName: 'addr',\n args: [node],\n });\n\n const result = addr === ZERO_ADDRESS ? null : addr;\n addrCache.set(key, { value: result, ts: Date.now() });\n return result;\n } catch {\n addrCache.set(key, { value: null, ts: Date.now() });\n return null;\n }\n}\n\n// ─── Reverse Resolution ────────────────────────────────────────\n\n/**\n * Look up the primary .mon name for an address.\n *\n * @param address - A 0x-prefixed Monad address\n * @param config - Optional client configuration\n * @returns The primary name (e.g. \"alice.mon\"), or null\n *\n * @example\n * ```ts\n * import { lookupAddress } from '@monadns/sdk'\n *\n * const name = await lookupAddress('0xa05a8BF1...')\n * // 'alice.mon'\n * ```\n */\nexport async function lookupAddress(\n address: string,\n config?: MNSClientConfig,\n): Promise<string | null> {\n const key = address.toLowerCase();\n const cached = getCached(nameCache, key);\n if (cached !== undefined) return cached;\n\n try {\n const client = getMNSClient(config);\n const reverseNode = namehash(\n `${key.slice(2)}.addr.reverse`,\n ) as `0x${string}`;\n\n const resolver = await client.readContract({\n address: MNS_REGISTRY,\n abi: registryAbi,\n functionName: 'resolver',\n args: [reverseNode],\n });\n\n if (resolver === ZERO_ADDRESS) {\n nameCache.set(key, { value: null, ts: Date.now() });\n return null;\n }\n\n const name = await client.readContract({\n address: resolver,\n abi: resolverAbi,\n functionName: 'name',\n args: [reverseNode],\n });\n\n const result = name || null;\n nameCache.set(key, { value: result, ts: Date.now() });\n return result;\n } catch {\n nameCache.set(key, { value: null, ts: Date.now() });\n return null;\n }\n}\n\n// ─── Text Records ──────────────────────────────────────────────\n\n/**\n * Get a text record for a .mon name.\n *\n * @param name - Full name including .mon\n * @param key - The text record key (e.g. \"avatar\", \"url\", \"com.twitter\")\n * @param config - Optional client configuration\n *\n * @example\n * ```ts\n * const avatar = await getTextRecord('alice.mon', 'avatar')\n * const twitter = await getTextRecord('alice.mon', 'com.twitter')\n * ```\n */\nexport async function getTextRecord(\n name: string,\n key: string,\n config?: MNSClientConfig,\n): Promise<string | null> {\n try {\n const client = getMNSClient(config);\n const node = namehash(name.toLowerCase()) as `0x${string}`;\n\n const resolver = await client.readContract({\n address: MNS_REGISTRY,\n abi: registryAbi,\n functionName: 'resolver',\n args: [node],\n });\n\n if (resolver === ZERO_ADDRESS) return null;\n\n const value = await client.readContract({\n address: resolver,\n abi: resolverAbi,\n functionName: 'text',\n args: [node, key],\n });\n\n return value || null;\n } catch {\n return null;\n }\n}\n\n// ─── Ownership & Registry Info ─────────────────────────────────\n\n/**\n * Get the owner of a .mon name.\n *\n * @param name - Full name including .mon (e.g. \"alice.mon\")\n * @param config - Optional client configuration\n * @returns The owner address, or null if not registered\n *\n * @example\n * ```ts\n * const owner = await getOwner('alice.mon')\n * // '0xa05a8BF1eda5bbC2b3aCAF03D04f77bD7d66Cc47'\n * ```\n */\nexport async function getOwner(\n name: string,\n config?: MNSClientConfig,\n): Promise<string | null> {\n try {\n const client = getMNSClient(config);\n const node = namehash(name.toLowerCase()) as `0x${string}`;\n\n const owner = await client.readContract({\n address: MNS_REGISTRY,\n abi: registryAbi,\n functionName: 'owner',\n args: [node],\n });\n\n return owner === ZERO_ADDRESS ? null : owner;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the resolver address for a .mon name.\n *\n * @param name - Full name including .mon\n * @param config - Optional client configuration\n * @returns The resolver contract address, or null if not set\n *\n * @example\n * ```ts\n * const resolver = await getResolver('alice.mon')\n * // '0xa2eb94c88e55d944aced2066c5cec9b759801f97'\n * ```\n */\nexport async function getResolver(\n name: string,\n config?: MNSClientConfig,\n): Promise<string | null> {\n try {\n const client = getMNSClient(config);\n const node = namehash(name.toLowerCase()) as `0x${string}`;\n\n const resolver = await client.readContract({\n address: MNS_REGISTRY,\n abi: registryAbi,\n functionName: 'resolver',\n args: [node],\n });\n\n return resolver === ZERO_ADDRESS ? null : resolver;\n } catch {\n return null;\n }\n}\n\n/**\n * Get expiry timestamp for a .mon name.\n *\n * @param name - Full name including .mon\n * @param config - Optional client configuration\n * @returns Unix timestamp (seconds) when the name expires, or null if not found\n *\n * @example\n * ```ts\n * const expiry = await getExpiry('alice.mon')\n * // 1735689600 (Unix timestamp)\n *\n * const expiryDate = new Date(expiry * 1000)\n * const daysLeft = Math.floor((expiry * 1000 - Date.now()) / (1000 * 60 * 60 * 24))\n * ```\n */\nexport async function getExpiry(\n name: string,\n config?: MNSClientConfig,\n): Promise<number | null> {\n try {\n const client = getMNSClient(config);\n const label = name.replace('.mon', '');\n const labelHash = keccak256(toBytes(label));\n\n const expiry = await client.readContract({\n address: MNS_BASE_REGISTRAR,\n abi: [\n {\n name: 'nameExpires',\n type: 'function',\n inputs: [{ name: 'id', type: 'uint256' }],\n outputs: [{ name: '', type: 'uint256' }],\n stateMutability: 'view',\n },\n ] as const,\n functionName: 'nameExpires',\n args: [BigInt(labelHash)],\n });\n\n return Number(expiry);\n } catch {\n return null;\n }\n}\n\n/**\n * Check if a .mon name is available for registration.\n *\n * @param name - Full name including .mon\n * @param config - Optional client configuration\n * @returns true if available (not registered), false if taken\n *\n * @example\n * ```ts\n * const available = await getAvailable('alice.mon')\n * if (available) {\n * console.log('alice.mon is available!')\n * }\n * ```\n */\nexport async function getAvailable(\n name: string,\n config?: MNSClientConfig,\n): Promise<boolean> {\n const addr = await resolveName(name, config);\n return addr === null;\n}\n\n// ─── Helpers ───────────────────────────────────────────────────\n\n/**\n * Get a display-friendly name for an address.\n * Returns the .mon name if set, otherwise a truncated address.\n *\n * @example\n * ```ts\n * const display = await getDisplayName('0xa05a8BF1...')\n * // 'alice.mon' or '0xa05a...Cc47'\n * ```\n */\nexport async function getDisplayName(\n address: string,\n config?: MNSClientConfig,\n): Promise<string> {\n const name = await lookupAddress(address, config);\n if (name) return name;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\n/**\n * Smart resolver — accepts either a .mon name or a raw address.\n * Useful for input fields where users can type either.\n *\n * @returns The resolved address, or null if invalid/not found\n *\n * @example\n * ```ts\n * const addr = await resolveInput('alice.mon') // resolves name\n * const addr = await resolveInput('alice') // tries alice.mon\n * const addr = await resolveInput('0xa05a...') // passes through\n * ```\n */\nexport async function resolveInput(\n input: string,\n config?: MNSClientConfig,\n): Promise<string | null> {\n const trimmed = input.trim();\n if (!trimmed) return null;\n\n if (trimmed.startsWith('0x') && trimmed.length === 42) return trimmed;\n if (trimmed.endsWith('.mon')) return resolveName(trimmed, config);\n\n // Try appending .mon\n return resolveName(`${trimmed}.mon`, config);\n}\n\n/**\n * Get a resolved avatar URL for a .mon name.\n *\n * Handles multiple avatar formats:\n * - Direct HTTPS URLs: returned as-is\n * - IPFS URIs (ipfs://...): resolved via public gateway\n * - NFT references (eip155:chainId/erc721:contract/tokenId): fetches tokenURI and extracts image\n *\n * @param name - Full name including .mon\n * @param config - Optional client configuration\n * @returns A usable HTTPS URL, or null\n *\n * @example\n * ```ts\n * const avatarUrl = await getAvatarUrl('alice.mon')\n * // 'https://example.com/avatar.png'\n * ```\n */\nexport async function getAvatarUrl(\n name: string,\n config?: MNSClientConfig,\n): Promise<string | null> {\n const raw = await getTextRecord(name, 'avatar', config);\n if (!raw) return null;\n\n // Direct HTTP(S) URL\n if (raw.startsWith('http://') || raw.startsWith('https://')) {\n return raw;\n }\n\n // IPFS\n if (raw.startsWith('ipfs://')) {\n const hash = raw.slice(7);\n return `https://ipfs.io/ipfs/${hash}`;\n }\n\n // NFT reference: eip155:{chainId}/erc721:{contract}/{tokenId}\n // or eip155:{chainId}/erc1155:{contract}/{tokenId}\n const nftMatch = raw.match(\n /^eip155:(\\d+)\\/(erc721|erc1155):0x([a-fA-F0-9]{40})\\/(\\d+)$/,\n );\n if (nftMatch) {\n try {\n const client = getMNSClient(config);\n const contract = `0x${nftMatch[3]}` as `0x${string}`;\n const tokenId = BigInt(nftMatch[4]);\n\n const tokenUriAbi = [\n {\n name: nftMatch[2] === 'erc721' ? 'tokenURI' : 'uri',\n type: 'function',\n inputs: [{ name: 'tokenId', type: 'uint256' }],\n outputs: [{ name: '', type: 'string' }],\n stateMutability: 'view',\n },\n ] as const;\n\n let tokenUri = (await client.readContract({\n address: contract,\n abi: tokenUriAbi,\n functionName: nftMatch[2] === 'erc721' ? 'tokenURI' : 'uri',\n args: [tokenId],\n })) as string;\n\n // Resolve IPFS tokenURI\n if (tokenUri.startsWith('ipfs://')) {\n tokenUri = `https://ipfs.io/ipfs/${tokenUri.slice(7)}`;\n }\n\n // Fetch metadata JSON and extract image\n const res = await fetch(tokenUri);\n const metadata = await res.json();\n let image = metadata.image || metadata.image_url || null;\n\n if (image && image.startsWith('ipfs://')) {\n image = `https://ipfs.io/ipfs/${image.slice(7)}`;\n }\n\n return image;\n } catch {\n return null;\n }\n }\n\n // data: URIs\n if (raw.startsWith('data:')) {\n return raw;\n }\n\n return null;\n}\n\n/**\n * Clear the internal resolution cache.\n * Useful after a new registration.\n */\nexport function clearCache() {\n nameCache.clear();\n addrCache.clear();\n}\n","import {\n createPublicClient,\n http,\n type PublicClient,\n type Chain,\n type Transport,\n} from 'viem';\nimport { monad } from 'viem/chains';\n\nexport type MNSClientConfig = {\n /** Custom RPC URL. Defaults to the public Monad RPC. */\n rpcUrl?: string;\n /** Existing viem PublicClient to reuse instead of creating a new one. */\n client?: PublicClient<Transport, Chain>;\n};\n\nlet defaultClient: PublicClient<Transport, Chain> | null = null;\n\n/**\n * Get or create the MNS public client.\n * Reuses a singleton by default; pass config to override.\n */\nexport function getMNSClient(\n config?: MNSClientConfig,\n): PublicClient<Transport, Chain> {\n if (config?.client) return config.client;\n\n if (config?.rpcUrl) {\n return createPublicClient({\n chain: monad,\n transport: http(config.rpcUrl),\n });\n }\n\n if (!defaultClient) {\n defaultClient = createPublicClient({\n chain: monad,\n transport: http(),\n });\n }\n\n return defaultClient;\n}\n","export const MNS_REGISTRY =\n '0x13f963486e741c8d3fcdc0a34a910920339a19ce' as const;\nexport const MNS_PUBLIC_RESOLVER =\n '0xa2eb94c88e55d944aced2066c5cec9b759801f97' as const;\nexport const MNS_CONTROLLER =\n '0x98866c55adbc73ec6c272bb3604ddbdee3f282a8' as const;\nexport const MNS_BASE_REGISTRAR =\n '0x104a49db9318c284d462841b6940bdb46624ca55' as const;\n\nexport const ZERO_ADDRESS =\n '0x0000000000000000000000000000000000000000' as const;\n\nexport const registryAbi = [\n {\n name: 'resolver',\n type: 'function',\n inputs: [{ name: 'node', type: 'bytes32' }],\n outputs: [{ name: '', type: 'address' }],\n stateMutability: 'view',\n },\n {\n name: 'owner',\n type: 'function',\n inputs: [{ name: 'node', type: 'bytes32' }],\n outputs: [{ name: '', type: 'address' }],\n stateMutability: 'view',\n },\n] as const;\n\nexport const resolverAbi = [\n {\n name: 'addr',\n type: 'function',\n inputs: [{ name: 'node', type: 'bytes32' }],\n outputs: [{ name: '', type: 'address' }],\n stateMutability: 'view',\n },\n {\n name: 'name',\n type: 'function',\n inputs: [{ name: 'node', type: 'bytes32' }],\n outputs: [{ name: '', type: 'string' }],\n stateMutability: 'view',\n },\n {\n name: 'text',\n type: 'function',\n inputs: [\n { name: 'node', type: 'bytes32' },\n { name: 'key', type: 'string' },\n ],\n outputs: [{ name: '', type: 'string' }],\n stateMutability: 'view',\n },\n] as const;\n","import { namehash } from 'viem';\nimport { getMNSClient, type MNSClientConfig } from './client';\nimport { MNS_CONTROLLER, MNS_PUBLIC_RESOLVER } from './constants';\n\n/**\n * MNS Write Helpers\n *\n * These return transaction parameters ({ address, abi, functionName, args, value })\n * that you pass to wagmi's writeContract or any wallet client.\n * The user signs with their own wallet.\n */\n\n// ─── ABIs ──────────────────────────────────────────────────────\n\nexport const controllerReadAbi = [\n {\n name: 'available',\n type: 'function',\n inputs: [{ name: 'label', type: 'string' }],\n outputs: [{ name: '', type: 'bool' }],\n stateMutability: 'view',\n },\n {\n name: 'rentPrice',\n type: 'function',\n inputs: [\n { name: 'label', type: 'string' },\n { name: 'duration', type: 'uint256' },\n ],\n outputs: [{ name: '', type: 'uint256' }],\n stateMutability: 'view',\n },\n {\n name: 'hasClaimedFreebie',\n type: 'function',\n inputs: [{ name: 'user', type: 'address' }],\n outputs: [{ name: '', type: 'bool' }],\n stateMutability: 'view',\n },\n] as const;\n\nexport const controllerWriteAbi = [\n {\n name: 'register',\n type: 'function',\n inputs: [\n { name: 'label', type: 'string' },\n { name: 'owner', type: 'address' },\n { name: 'duration', type: 'uint256' },\n ],\n outputs: [{ name: '', type: 'uint256' }],\n stateMutability: 'payable',\n },\n] as const;\n\nexport const resolverWriteAbi = [\n {\n name: 'setText',\n type: 'function',\n inputs: [\n { name: 'node', type: 'bytes32' },\n { name: 'key', type: 'string' },\n { name: 'value', type: 'string' },\n ],\n outputs: [],\n stateMutability: 'nonpayable',\n },\n {\n name: 'setAddr',\n type: 'function',\n inputs: [\n { name: 'node', type: 'bytes32' },\n { name: 'a', type: 'address' },\n ],\n outputs: [],\n stateMutability: 'nonpayable',\n },\n] as const;\n\n// ─── Types ─────────────────────────────────────────────────────\n\nexport type RegistrationInfo = {\n available: boolean;\n price: bigint;\n isFreebie: boolean;\n hasClaimed: boolean;\n duration: bigint;\n label: string;\n};\n\n// ─── Registration ──────────────────────────────────────────────\n\nconst ONE_YEAR = BigInt(365 * 24 * 60 * 60);\n\n/**\n * Get all info needed before registration.\n *\n * @example\n * ```ts\n * const info = await getRegistrationInfo('alice', userAddress)\n * // { available: true, price: 96831564n..., isFreebie: true, ... }\n * ```\n */\nexport async function getRegistrationInfo(\n label: string,\n userAddress: string,\n durationYears = 1,\n config?: MNSClientConfig,\n): Promise<RegistrationInfo> {\n const client = getMNSClient(config);\n const duration = ONE_YEAR * BigInt(durationYears);\n\n const [available, price, hasClaimed, balance] = await Promise.all([\n client.readContract({\n address: MNS_CONTROLLER,\n abi: controllerReadAbi,\n functionName: 'available',\n args: [label],\n }),\n client.readContract({\n address: MNS_CONTROLLER,\n abi: controllerReadAbi,\n functionName: 'rentPrice',\n args: [label, duration],\n }),\n client.readContract({\n address: MNS_CONTROLLER,\n abi: controllerReadAbi,\n functionName: 'hasClaimedFreebie',\n args: [userAddress as `0x${string}`],\n }),\n client.getBalance({ address: userAddress as `0x${string}` }),\n ]);\n\n const isFreebie = balance >= 10n * 10n ** 18n && !hasClaimed;\n\n return { available, price, isFreebie, hasClaimed, duration, label };\n}\n\n/**\n * Get transaction parameters for registering a .mon name.\n * Pass the result to wagmi's writeContract.\n *\n * @example\n * ```ts\n * const tx = await getRegisterTx('alice', userAddress)\n * writeContract(tx)\n * ```\n */\nexport async function getRegisterTx(\n label: string,\n ownerAddress: string,\n durationYears = 1,\n config?: MNSClientConfig,\n) {\n const info = await getRegistrationInfo(\n label,\n ownerAddress,\n durationYears,\n config,\n );\n\n if (!info.available) {\n throw new Error(`${label}.mon is not available`);\n }\n\n return {\n address: MNS_CONTROLLER,\n abi: controllerWriteAbi,\n functionName: 'register' as const,\n args: [label, ownerAddress as `0x${string}`, info.duration] as const,\n value: info.isFreebie ? 0n : info.price,\n gas: 3_000_000n,\n _meta: {\n label,\n isFreebie: info.isFreebie,\n price: info.price,\n duration: info.duration,\n },\n };\n}\n\n// ─── Text Records ──────────────────────────────────────────────\n\n/**\n * Get transaction parameters for setting a text record.\n * The connected user must own the name.\n *\n * @example\n * ```ts\n * const tx = getSetTextTx('alice.mon', 'avatar', 'https://example.com/pic.png')\n * writeContract(tx)\n * ```\n */\nexport function getSetTextTx(name: string, key: string, value: string) {\n const node = namehash(\n name.endsWith('.mon') ? name : `${name}.mon`,\n ) as `0x${string}`;\n\n return {\n address: MNS_PUBLIC_RESOLVER,\n abi: resolverWriteAbi,\n functionName: 'setText' as const,\n args: [node, key, value] as const,\n };\n}\n\n/**\n * Get transaction parameters for setting the address record.\n */\nexport function getSetAddrTx(name: string, addr: string) {\n const node = namehash(\n name.endsWith('.mon') ? name : `${name}.mon`,\n ) as `0x${string}`;\n\n return {\n address: MNS_PUBLIC_RESOLVER,\n abi: resolverWriteAbi,\n functionName: 'setAddr' as const,\n args: [node, addr as `0x${string}`] as const,\n };\n}\n\nexport const TEXT_RECORD_KEYS = {\n avatar: 'avatar',\n url: 'url',\n description: 'description',\n email: 'email',\n twitter: 'com.twitter',\n github: 'com.github',\n discord: 'com.discord',\n telegram: 'org.telegram',\n} as const;\n"],"mappings":"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","names":["import_viem","import_viem"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -58,6 +58,67 @@ declare function lookupAddress(address: string, config?: MNSClientConfig): Promi
|
|
|
58
58
|
* ```
|
|
59
59
|
*/
|
|
60
60
|
declare function getTextRecord(name: string, key: string, config?: MNSClientConfig): Promise<string | null>;
|
|
61
|
+
/**
|
|
62
|
+
* Get the owner of a .mon name.
|
|
63
|
+
*
|
|
64
|
+
* @param name - Full name including .mon (e.g. "alice.mon")
|
|
65
|
+
* @param config - Optional client configuration
|
|
66
|
+
* @returns The owner address, or null if not registered
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* const owner = await getOwner('alice.mon')
|
|
71
|
+
* // '0xa05a8BF1eda5bbC2b3aCAF03D04f77bD7d66Cc47'
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
declare function getOwner(name: string, config?: MNSClientConfig): Promise<string | null>;
|
|
75
|
+
/**
|
|
76
|
+
* Get the resolver address for a .mon name.
|
|
77
|
+
*
|
|
78
|
+
* @param name - Full name including .mon
|
|
79
|
+
* @param config - Optional client configuration
|
|
80
|
+
* @returns The resolver contract address, or null if not set
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* const resolver = await getResolver('alice.mon')
|
|
85
|
+
* // '0xa2eb94c88e55d944aced2066c5cec9b759801f97'
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
declare function getResolver(name: string, config?: MNSClientConfig): Promise<string | null>;
|
|
89
|
+
/**
|
|
90
|
+
* Get expiry timestamp for a .mon name.
|
|
91
|
+
*
|
|
92
|
+
* @param name - Full name including .mon
|
|
93
|
+
* @param config - Optional client configuration
|
|
94
|
+
* @returns Unix timestamp (seconds) when the name expires, or null if not found
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```ts
|
|
98
|
+
* const expiry = await getExpiry('alice.mon')
|
|
99
|
+
* // 1735689600 (Unix timestamp)
|
|
100
|
+
*
|
|
101
|
+
* const expiryDate = new Date(expiry * 1000)
|
|
102
|
+
* const daysLeft = Math.floor((expiry * 1000 - Date.now()) / (1000 * 60 * 60 * 24))
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
declare function getExpiry(name: string, config?: MNSClientConfig): Promise<number | null>;
|
|
106
|
+
/**
|
|
107
|
+
* Check if a .mon name is available for registration.
|
|
108
|
+
*
|
|
109
|
+
* @param name - Full name including .mon
|
|
110
|
+
* @param config - Optional client configuration
|
|
111
|
+
* @returns true if available (not registered), false if taken
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```ts
|
|
115
|
+
* const available = await getAvailable('alice.mon')
|
|
116
|
+
* if (available) {
|
|
117
|
+
* console.log('alice.mon is available!')
|
|
118
|
+
* }
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
declare function getAvailable(name: string, config?: MNSClientConfig): Promise<boolean>;
|
|
61
122
|
/**
|
|
62
123
|
* Get a display-friendly name for an address.
|
|
63
124
|
* Returns the .mon name if set, otherwise a truncated address.
|
|
@@ -83,15 +144,6 @@ declare function getDisplayName(address: string, config?: MNSClientConfig): Prom
|
|
|
83
144
|
* ```
|
|
84
145
|
*/
|
|
85
146
|
declare function resolveInput(input: string, config?: MNSClientConfig): Promise<string | null>;
|
|
86
|
-
/**
|
|
87
|
-
* Check if a .mon name is registered.
|
|
88
|
-
*
|
|
89
|
-
* @example
|
|
90
|
-
* ```ts
|
|
91
|
-
* const taken = await isRegistered('alice.mon')
|
|
92
|
-
* ```
|
|
93
|
-
*/
|
|
94
|
-
declare function isRegistered(name: string, config?: MNSClientConfig): Promise<boolean>;
|
|
95
147
|
/**
|
|
96
148
|
* Get a resolved avatar URL for a .mon name.
|
|
97
149
|
*
|
|
@@ -364,5 +416,6 @@ declare const TEXT_RECORD_KEYS: {
|
|
|
364
416
|
declare const MNS_REGISTRY: "0x13f963486e741c8d3fcdc0a34a910920339a19ce";
|
|
365
417
|
declare const MNS_PUBLIC_RESOLVER: "0xa2eb94c88e55d944aced2066c5cec9b759801f97";
|
|
366
418
|
declare const MNS_CONTROLLER: "0x98866c55adbc73ec6c272bb3604ddbdee3f282a8";
|
|
419
|
+
declare const MNS_BASE_REGISTRAR: "0x104a49db9318c284d462841b6940bdb46624ca55";
|
|
367
420
|
|
|
368
|
-
export { type MNSClientConfig, MNS_CONTROLLER, MNS_PUBLIC_RESOLVER, MNS_REGISTRY, type RegistrationInfo, TEXT_RECORD_KEYS, clearCache, controllerReadAbi, controllerWriteAbi, getAvatarUrl, getDisplayName, getMNSClient, getRegisterTx, getRegistrationInfo, getSetAddrTx, getSetTextTx, getTextRecord,
|
|
421
|
+
export { type MNSClientConfig, MNS_BASE_REGISTRAR, MNS_CONTROLLER, MNS_PUBLIC_RESOLVER, MNS_REGISTRY, type RegistrationInfo, TEXT_RECORD_KEYS, clearCache, controllerReadAbi, controllerWriteAbi, getAvailable, getAvatarUrl, getDisplayName, getExpiry, getMNSClient, getOwner, getRegisterTx, getRegistrationInfo, getResolver, getSetAddrTx, getSetTextTx, getTextRecord, lookupAddress, resolveInput, resolveName, resolverWriteAbi };
|
package/dist/index.d.ts
CHANGED
|
@@ -58,6 +58,67 @@ declare function lookupAddress(address: string, config?: MNSClientConfig): Promi
|
|
|
58
58
|
* ```
|
|
59
59
|
*/
|
|
60
60
|
declare function getTextRecord(name: string, key: string, config?: MNSClientConfig): Promise<string | null>;
|
|
61
|
+
/**
|
|
62
|
+
* Get the owner of a .mon name.
|
|
63
|
+
*
|
|
64
|
+
* @param name - Full name including .mon (e.g. "alice.mon")
|
|
65
|
+
* @param config - Optional client configuration
|
|
66
|
+
* @returns The owner address, or null if not registered
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* const owner = await getOwner('alice.mon')
|
|
71
|
+
* // '0xa05a8BF1eda5bbC2b3aCAF03D04f77bD7d66Cc47'
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
declare function getOwner(name: string, config?: MNSClientConfig): Promise<string | null>;
|
|
75
|
+
/**
|
|
76
|
+
* Get the resolver address for a .mon name.
|
|
77
|
+
*
|
|
78
|
+
* @param name - Full name including .mon
|
|
79
|
+
* @param config - Optional client configuration
|
|
80
|
+
* @returns The resolver contract address, or null if not set
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* const resolver = await getResolver('alice.mon')
|
|
85
|
+
* // '0xa2eb94c88e55d944aced2066c5cec9b759801f97'
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
declare function getResolver(name: string, config?: MNSClientConfig): Promise<string | null>;
|
|
89
|
+
/**
|
|
90
|
+
* Get expiry timestamp for a .mon name.
|
|
91
|
+
*
|
|
92
|
+
* @param name - Full name including .mon
|
|
93
|
+
* @param config - Optional client configuration
|
|
94
|
+
* @returns Unix timestamp (seconds) when the name expires, or null if not found
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```ts
|
|
98
|
+
* const expiry = await getExpiry('alice.mon')
|
|
99
|
+
* // 1735689600 (Unix timestamp)
|
|
100
|
+
*
|
|
101
|
+
* const expiryDate = new Date(expiry * 1000)
|
|
102
|
+
* const daysLeft = Math.floor((expiry * 1000 - Date.now()) / (1000 * 60 * 60 * 24))
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
declare function getExpiry(name: string, config?: MNSClientConfig): Promise<number | null>;
|
|
106
|
+
/**
|
|
107
|
+
* Check if a .mon name is available for registration.
|
|
108
|
+
*
|
|
109
|
+
* @param name - Full name including .mon
|
|
110
|
+
* @param config - Optional client configuration
|
|
111
|
+
* @returns true if available (not registered), false if taken
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```ts
|
|
115
|
+
* const available = await getAvailable('alice.mon')
|
|
116
|
+
* if (available) {
|
|
117
|
+
* console.log('alice.mon is available!')
|
|
118
|
+
* }
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
declare function getAvailable(name: string, config?: MNSClientConfig): Promise<boolean>;
|
|
61
122
|
/**
|
|
62
123
|
* Get a display-friendly name for an address.
|
|
63
124
|
* Returns the .mon name if set, otherwise a truncated address.
|
|
@@ -83,15 +144,6 @@ declare function getDisplayName(address: string, config?: MNSClientConfig): Prom
|
|
|
83
144
|
* ```
|
|
84
145
|
*/
|
|
85
146
|
declare function resolveInput(input: string, config?: MNSClientConfig): Promise<string | null>;
|
|
86
|
-
/**
|
|
87
|
-
* Check if a .mon name is registered.
|
|
88
|
-
*
|
|
89
|
-
* @example
|
|
90
|
-
* ```ts
|
|
91
|
-
* const taken = await isRegistered('alice.mon')
|
|
92
|
-
* ```
|
|
93
|
-
*/
|
|
94
|
-
declare function isRegistered(name: string, config?: MNSClientConfig): Promise<boolean>;
|
|
95
147
|
/**
|
|
96
148
|
* Get a resolved avatar URL for a .mon name.
|
|
97
149
|
*
|
|
@@ -364,5 +416,6 @@ declare const TEXT_RECORD_KEYS: {
|
|
|
364
416
|
declare const MNS_REGISTRY: "0x13f963486e741c8d3fcdc0a34a910920339a19ce";
|
|
365
417
|
declare const MNS_PUBLIC_RESOLVER: "0xa2eb94c88e55d944aced2066c5cec9b759801f97";
|
|
366
418
|
declare const MNS_CONTROLLER: "0x98866c55adbc73ec6c272bb3604ddbdee3f282a8";
|
|
419
|
+
declare const MNS_BASE_REGISTRAR: "0x104a49db9318c284d462841b6940bdb46624ca55";
|
|
367
420
|
|
|
368
|
-
export { type MNSClientConfig, MNS_CONTROLLER, MNS_PUBLIC_RESOLVER, MNS_REGISTRY, type RegistrationInfo, TEXT_RECORD_KEYS, clearCache, controllerReadAbi, controllerWriteAbi, getAvatarUrl, getDisplayName, getMNSClient, getRegisterTx, getRegistrationInfo, getSetAddrTx, getSetTextTx, getTextRecord,
|
|
421
|
+
export { type MNSClientConfig, MNS_BASE_REGISTRAR, MNS_CONTROLLER, MNS_PUBLIC_RESOLVER, MNS_REGISTRY, type RegistrationInfo, TEXT_RECORD_KEYS, clearCache, controllerReadAbi, controllerWriteAbi, getAvailable, getAvatarUrl, getDisplayName, getExpiry, getMNSClient, getOwner, getRegisterTx, getRegistrationInfo, getResolver, getSetAddrTx, getSetTextTx, getTextRecord, lookupAddress, resolveInput, resolveName, resolverWriteAbi };
|