About XRPL
home

PermissionedDomains

์ฃผ์š” ๋‚ด์šฉ
๋„๋ฉ”์ธ ์ƒ์„ฑยท์ •์ฑ… ๊ด€๋ฆฌ
ํด๋”๋ช…
PermissionedDomains

์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰ ๋ช…๋ น์–ด

#1) ํŠน์ • Credential ์†Œ์œ ์ž๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ Domain ์ƒ์„ฑ $npx ts-node xrpl/PermissionedDomains/createDomain.ts #2) Domain ์‚ญ์ œ $npx ts-node xrpl/PermissionedDomains/deleteDomain.ts #3) ํ•ด๋‹น Domain์— ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ Credential ๋ฐ ์†Œ์œ ์ž ๋ฆฌ์ŠคํŠธ ๋ณด๊ธฐ (Optional) $npx ts-node xrpl/PermissionedDomains/AcceptedCredentials.ts #์—ฌ๊ธฐ์„œ๋Š” ์ƒ์„ฑ ํ›„ ์ถœ๋ ฅ๋˜๋Š” DomainID(created): 2A65BCCE9715703A09460B44812BB65D41B9406A42D0CC66979E385C5788#### ๋ฅผ ๋‚˜๋จธ์ง€ ์Šคํฌ๋ฆฝํŠธ์— ๋„ฃ์–ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
Bash
๋ณต์‚ฌ

1. Permissioned Domain์ด๋ž€?

Permissioned Domain์€ ์ ‘๊ทผ ์ •์ฑ…(Access Policy)์„ ์˜จ์ฒด์ธ์— ๋“ฑ๋กํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
์Šค์Šค๋กœ๋Š” ์•„๋ฌด ํ–‰๋™๋„ ํ•˜์ง€ ์•Š์ง€๋งŒ, ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค(์˜ˆ: Permissioned DEX, Lending Vault ๋“ฑ)์— ๋„๋ฉ”์ธ ID๋ฅผ ์—ฐ๊ฒฐํ•˜๋ฉด
ํ•ด๋‹น ๋ฆฌ์†Œ์Šค๊ฐ€ ์ด ๋„๋ฉ”์ธ์˜ ๊ทœ์น™์„ ๋”ฐ๋ผ ํŠธ๋žœ์žญ์…˜์„ ํ—ˆ์šฉํ•˜๊ฑฐ๋‚˜ ๊ฑฐ๋ถ€ํ•  ์ˆ˜ ์žˆ๋‹ค.
โ€ข
๋„๋ฉ”์ธ์˜ ๊ทœ์น™ = AcceptedCredentials
1~10๊ฐœ์˜ โ€œํ—ˆ์šฉ ์ž๊ฒฉโ€์„ ๋‚˜์—ดํ•œ๋‹ค.
๊ฐ ์ž๊ฒฉ์€ ๋ฐœ๊ธ‰์ž(Issuer)์™€ CredentialType(hex)์˜ ์กฐํ•ฉ์ด๋‹ค.
โ€ข
์ ‘๊ทผ ํ—ˆ์šฉ ์กฐ๊ฑด
ํŠธ๋žœ์žญ์…˜์„ ๋ณด๋‚ด๋Š” ๊ณ„์ •์ด ์ด ๋„๋ฉ”์ธ์—์„œ ํ—ˆ์šฉํ•œ Credential์„ ์ตœ์†Œ 1๊ฐœ ์ด์ƒ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.
ํ•ด๋‹น Credential์€ ์ˆ˜๋ฝ๋จ(accepted) ์ƒํƒœ์ด๋ฉฐ ๋งŒ๋ฃŒ๋˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.

2. ์™œ ํ•„์š”ํ•œ๊ฐ€?

โ€ข
๊ทœ์ œ ์ค€์ˆ˜
๊ธˆ์œต ์„œ๋น„์Šค, KYC/AML ์š”๊ตฌ์‚ฌํ•ญ์ด ์žˆ๋Š” ํ”„๋กœ์ ํŠธ์—์„œ ํ•„์ˆ˜.
โ€ข
์ •์ฑ… ๋ถ„๋ฆฌ
์ •์ฑ… ๋ณ€๊ฒฝ ์‹œ, ๋ฆฌ์†Œ์Šค ์ฝ”๋“œ๋‚˜ ์ฃผ์†Œ๋ฅผ ์ˆ˜์ •ํ•  ํ•„์š” ์—†์ด ๋„๋ฉ”์ธ ๊ทœ์น™๋งŒ ์—…๋ฐ์ดํŠธํ•˜๋ฉด ๋œ๋‹ค.
โ€ข
์šด์˜ ์œ ์—ฐ์„ฑ
๋ฐœ๊ธ‰/์ˆ˜๋ฝ/๋งŒ๋ฃŒ๋ฅผ ํ†ตํ•ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ ‘๊ทผ์ž ๋ชฉ๋ก์ด ๋ณ€๋™๋  ์ˆ˜ ์žˆ๋‹ค.
โ€ข
์†Œ์œ ๊ถŒ ๋ช…ํ™•
๋„๋ฉ”์ธ์„ ๋งŒ๋“  ๊ณ„์ •(์˜ค๋„ˆ)๋งŒ ๊ทœ์น™ ๋ณ€๊ฒฝยท์‚ญ์ œ ๊ฐ€๋Šฅ.

3. ์‹œ๋‚˜๋ฆฌ์˜ค: createDomain โ†’ deleteDomain

์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋Š” ๋„๋ฉ”์ธ ์ƒ์„ฑ๊ณผ ์‚ญ์ œ๋งŒ ๋‹ค๋ฃฌ๋‹ค.
Credential ๋ฐœ๊ธ‰/์ˆ˜๋ฝ ์‹œ๋‚˜๋ฆฌ์˜ค์™€ ์กฐํ•ฉํ•˜๋ฉด, ๋„๋ฉ”์ธ์˜ ์‹ค์ œ ์ ‘๊ทผ์ œํ•œ ํšจ๊ณผ๊นŒ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

Step 1. ๋„๋ฉ”์ธ ์ƒ์„ฑ

โ€ข
์ฃผ์ฒด: ADMIN(๋„๋ฉ”์ธ ์˜ค๋„ˆ)
โ€ข
ํ–‰๋™: PermissionedDomainSet ํŠธ๋žœ์žญ์…˜ ์ „์†ก
โ€ข
๋‚ด์šฉ:
โ—ฆ
AcceptedCredentials: {Issuer: ADMIN, CredentialType: "KYC(hex)"}
โ†’ ADMIN์ด ๋ฐœ๊ธ‰ํ•œ KYC Credential์„ ๊ฐ€์ง„ ๊ณ„์ •๋งŒ ์ด ๋„๋ฉ”์ธ์— ์ ‘๊ทผ ๊ฐ€๋Šฅ
import { Client, Wallet, Transaction } from "xrpl" import path from "path" import dotenv from "dotenv" // .env ๋กœ๋“œ (ADMIN_SEED ํ•„์š”) dotenv.config({ path: path.join(__dirname, "..", ".env") }) // ๋ฌธ์ž์—ด์„ hex ์ธ์ฝ”๋”ฉํ•˜๋Š” ํ—ฌํผ ํ•จ์ˆ˜ const toHex = (s: string) => Buffer.from(s, "utf8").toString("hex") export async function createDomain() { const client = new Client("wss://s.devnet.rippletest.net:51233") await client.connect() const ADMIN_SEED = process.env.ADMIN_SEED if (!ADMIN_SEED) throw new Error("Missing env: ADMIN_SEED") // ๋ฐœํ–‰์ž(Admin) ์ง€๊ฐ‘ ๋กœ๋“œ const admin = Wallet.fromSeed(ADMIN_SEED) try { // PermissionedDomainSet ํŠธ๋žœ์žญ์…˜ ๊ตฌ์„ฑ const tx: Transaction = { TransactionType: "PermissionedDomainSet", Account: admin.address, // ์ƒˆ๋กœ์šด Domain ์ƒ์„ฑ ์‹œ DomainID๋Š” ์ƒ๋žต AcceptedCredentials: [ { Credential: { Issuer: admin.address, CredentialType: toHex("KYC"), // "KYC" โ†’ hex ์ธ์ฝ”๋”ฉ }, }, ], } // ํŠธ๋žœ์žญ์…˜ ์ž๋™ ๋ณด์™„ & ์„œ๋ช… const prepared = await client.autofill(tx) const signed = admin.sign(prepared) // ์ œ์ถœ ๋ฐ ๊ฒฐ๊ณผ ๋Œ€๊ธฐ const result: any = await client.submitAndWait(signed.tx_blob) // ์ „์ฒด ์‘๋‹ต ๋กœ๊ทธ ์ถœ๋ ฅ console.log(JSON.stringify(result, null, 2)) // meta ๋ฐ์ดํ„ฐ์—์„œ ์ƒ์„ฑ๋œ PermissionedDomain ๊ฐ์ฒด ํƒ์ƒ‰ const out = result.result ?? result const created = (out.meta?.AffectedNodes || []).find( (n: any) => n.CreatedNode?.LedgerEntryType === "PermissionedDomain" ) const domainId = created?.CreatedNode?.LedgerIndex || created?.CreatedNode?.NewFields?.DomainID || null if (domainId) { console.log("โœ… DomainID(created):", domainId) } else { console.warn("โš ๏ธ Could not locate DomainID in meta. Check node support/fields.") } return result } catch (err) { console.error("โŒ ๋„๋ฉ”์ธ ์ƒ์„ฑ ์‹คํŒจ:", err) throw err } finally { await client.disconnect() console.log("๐Ÿ”„ ์—ฐ๊ฒฐ ์ข…๋ฃŒ") } } // ์ง์ ‘ ์‹คํ–‰ ์‹œ ๋™์ž‘ if (require.main === module) { createDomain().catch((e) => { console.error(e) process.exit(1) }) }
TypeScript
๋ณต์‚ฌ
โ€ข
์ฝ˜์†”์— ์ƒ์„ฑ๋œ ๋„๋ฉ”์ธ ID(๋”ฐ๋กœ ๋ณต์‚ฌํ•ด ๋„๋ฉ”์ธ ์‚ญ์ œ ๋ฐ Credential ์กฐํšŒ ๋“ฑ์— ์‚ฌ์šฉ)
DomainID(created): 2A65BCCE9715703A09460B44812BB65D41B9406A42D0CC66979E385C5788####
Bash
๋ณต์‚ฌ
โ€ข
DomainID : Permissioned Domain์„ ๊ณ ์œ ํ•˜๊ฒŒ ์‹๋ณ„ํ•˜๋Š” 32๋ฐ”์ดํŠธ(256๋น„ํŠธ) ํ•ด์‹œ ๊ฐ’์œผ๋กœ, 64์ž๋ฆฌ hex ๋ฌธ์ž์—ด๋กœ ํ‘œ์‹œ๋จ

Step 2. ๋„๋ฉ”์ธ ์‚ญ์ œ

โ€ข
์ฃผ์ฒด: ADMIN
โ€ข
ํ–‰๋™: PermissionedDomainDelete ํŠธ๋žœ์žญ์…˜ ์ „์†ก
โ€ข
๋‚ด์šฉ: DomainID ์ง€์ • โ†’ ํ•ด๋‹น ๋„๋ฉ”์ธ์˜ ์ •์ฑ… ์ž์ฒด๊ฐ€ ์‚ฌ๋ผ์ง
import { Client, Wallet, Transaction } from "xrpl" import path from "path" import dotenv from "dotenv" // .env ๋กœ๋“œ (ADMIN_SEED ํ•„์š”) dotenv.config({ path: path.join(__dirname, "..", ".env") }) export async function deleteDomain() { const client = new Client("wss://s.devnet.rippletest.net:51233") await client.connect() const ADMIN_SEED = process.env.ADMIN_SEED if (!ADMIN_SEED) throw new Error("Missing env: ADMIN_SEED") // ๋ฐœํ–‰์ž(Admin) ์ง€๊ฐ‘ ๋กœ๋“œ const admin = Wallet.fromSeed(ADMIN_SEED) // โœ… createDomain ์‹คํ–‰ ๊ฒฐ๊ณผ ๋กœ๊ทธ์—์„œ ๋ณต์‚ฌํ•œ DomainID ์ž…๋ ฅ const DOMAIN_ID = "2A65BCCE9715703A09460B44812BB65D41B9406A42D0CC66979E385C5788####" try { // PermissionedDomainDelete ํŠธ๋žœ์žญ์…˜ ๊ตฌ์„ฑ const tx: Transaction = { TransactionType: "PermissionedDomainDelete", Account: admin.address, DomainID: DOMAIN_ID, } // ํŠธ๋žœ์žญ์…˜ ์ž๋™ ๋ณด์™„ & ์„œ๋ช… const prepared = await client.autofill(tx) const signed = admin.sign(prepared) // ์ œ์ถœ ๋ฐ ๊ฒฐ๊ณผ ๋Œ€๊ธฐ const result = await client.submitAndWait(signed.tx_blob) // ์ „์ฒด ์‘๋‹ต ์ถœ๋ ฅ console.log(JSON.stringify(result, null, 2)) return result } catch (err) { console.error("โŒ ๋„๋ฉ”์ธ ์‚ญ์ œ ์‹คํŒจ:", err) throw err } finally { await client.disconnect() console.log("๐Ÿ”„ ์—ฐ๊ฒฐ ์ข…๋ฃŒ") } } // ์ง์ ‘ ์‹คํ–‰ ์‹œ ๋™์ž‘ if (require.main === module) { deleteDomain().catch((e) => { console.error(e) process.exit(1) }) }
TypeScript
๋ณต์‚ฌ

(์˜ต์…˜)Step 3. ํŠน์ • ๋„๋ฉ”์ธ์˜ Accepted Credentials ์ •๋ณด ์กฐํšŒ

import { Client } from "xrpl" async function inspectDomain() { // XRPL Devnet ์—ฐ๊ฒฐ const client = new Client("wss://s.devnet.rippletest.net:51233") await client.connect() try { // createDomain ์‹คํ–‰ ๋กœ๊ทธ์—์„œ ๋ณต๋ถ™ํ•œ DomainID const DOMAIN_ID = "5771BD9BD9B9BC01816103C9E435E54630AFF83B607DC9BCB0005D'''''''''" // ledger_entry ๋ช…๋ น์œผ๋กœ Domain ๊ฐ์ฒด ์กฐํšŒ const r = await client.request({ command: "ledger_entry", index: DOMAIN_ID, }) // ๊ฒฐ๊ณผ๋ฅผ JSON ํฌ๋งท์œผ๋กœ ์ถœ๋ ฅ console.log(JSON.stringify(r, null, 2)) } catch (err) { console.error("โŒ ๋„๋ฉ”์ธ ์กฐํšŒ ์‹คํŒจ:", err) } finally { // ์—ฐ๊ฒฐ ์ข…๋ฃŒ await client.disconnect() console.log("๐Ÿ”„ ์—ฐ๊ฒฐ ์ข…๋ฃŒ") } } // ์ง์ ‘ ์‹คํ–‰๋œ ๊ฒฝ์šฐ ํ•จ์ˆ˜ ์‹คํ–‰ inspectDomain().catch((e) => { console.error(e) process.exit(1) })
TypeScript
๋ณต์‚ฌ
โ€ข
ํ•ด๋‹น ๋„๋ฉ”์ธ์˜ AcceptedCredentials ์ •๋ณด๋ฅผ ์ฝ˜์†”์— ์ถœ๋ ฅ