About XRPL
home

MPtokensV1

์ฃผ์š” ๋‚ด์šฉ
๋ฐœํ–‰์ž ์Šน์ธํ˜• ํ† ํฐ ๋ฐœํ–‰/์ „์†ก
ํด๋”๋ช…
MPtokensV1

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

#1) ์‚ฌ์ „ ๋ฐœํ–‰ ์ •์˜ ์ƒ์„ฑ(Admin) $npx ts-node xrpl/MPTokensV1/createIssuance.ts # ์‹คํ–‰ ํ›„ IssuanceID(created): 006419063CEBEB49FC20032206CE0F203138BFC59F1A#### ๊ธฐ๋กํ•ด๋‘๊ธฐ, ์ดํ›„ 2~5๋ฒˆ ์Šคํฌ๋ฆฝํŠธ์— ์“ฐ์ž„ #2) ํ™€๋” ๊ถŒํ•œ ๋ถ€์—ฌ : 1๋ฒˆ์—์„œ ํŠธ๋žœ์žญ์…˜์„ (tfMPTRequireAuth: true)๋กœ ๋ณด๋ƒˆ์„ ๋•Œ๋งŒ! -์•„๋‹ ๋•Œ์—๋„ ์˜ตํŠธ์ธ ํ•ด์•ผ ํ•จ. $npx ts-node xrpl/MPTokensV1/authorizeHolder.tsi #3) MPT ์ „์†ก $npx ts-node xrpl/MPTokensV1/sendMPT.ts #4) ๋ฐœํ–‰์ •์˜ ์‚ญ์ œ (๋ชจ๋“  ํ™€๋”๋“ค์˜ ํ•ด๋‹น ํ† ํฐ ์ž”์•ก์ด 0์ด์–ด์•ผ ๊ฐ€๋Šฅ) $npx ts-node xrpl/MPTokensV1/destroyIssuance.ts #5) ๋ฐœํ–‰๋œ ํ† ํฐ ๋ฝ/์–ธ๋ฝ (Optional) $npx ts-node xrpl/MPTokensV1/setIssuance.ts
Bash
๋ณต์‚ฌ

1. MPT(Multi-Purpose Token)์ด๋ž€?

MPT๋Š” XRPL์˜ ์ƒˆ๋กœ์šด ํŽ€์ €๋ธ” ํ† ํฐ ํƒ€์ž…์œผ๋กœ, ๊ธฐ์กด IOU(์–‘๋ฐฉํ–ฅ ํŠธ๋Ÿฌ์ŠคํŠธ๋ผ์ธ)๋ณด๋‹ค ๋‹จ์ˆœํ•œ ๋ฐœํ–‰ยท๋ณด์œ  ๋ชจ๋ธ์„ ์ œ๊ณตํ•œ๋‹ค.
ํ† ํฐ์€ ๋‘ ๊ฐ€์ง€ ์›์žฅ ๊ฐ์ฒด๋กœ ๋‹ค๋ค„์ง„๋‹ค:
โ€ข
MPTokenIssuance: ๋ฐœํ–‰ ์ •์˜(์Šค์ผ€์ผ, ์ตœ๋Œ€๋ฐœํ–‰๋Ÿ‰, ์ „์†ก/๋ฝ/ํด๋กœ๋ฐฑ/๊ถŒํ•œํ•„์š” ๋“ฑ์˜ ์ •์ฑ…)
โ€ข
MPToken: ๊ฐœ๋ณ„ ๊ณ„์ •์ด ํŠน์ • ๋ฐœํ–‰๋ณธ์„ ์–ผ๋งˆ๋‚˜ ๋ณด์œ ํ•˜๋Š”์ง€
v1์˜ ํŠน์ง•: ์ง์ ‘ ๊ฒฐ์ œ๋งŒ ์ง€์›(๊ณ„์ •โ†’๊ณ„์ •). DEX ๊ฑฐ๋ž˜๋Š” ๋ถˆ๊ฐ€.

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

โ€ข
๊ฐ„๊ฒฐํ•œ ์šด์˜ ๋ชจ๋ธ
Trustline ์—†์ด ๋ฐœํ–‰ยท์ „์†ก ์ค‘์‹ฌ์˜ ๋‹จ๋ฐฉํ–ฅ ๋ชจ๋ธ.
โ€ข
์ •์ฑ… ์ผ์›ํ™”
์ „์†ก ๊ฐ€๋Šฅ ์—ฌ๋ถ€, ๊ถŒํ•œ ํ•„์š”(RequireAuth), ๋ฝ/์–ธ๋ฝ, ํด๋กœ๋ฐฑ ๋“ฑ์˜ ๋ฐœํ–‰๋ณธ ๋‹จ์œ„ ์ •์ฑ…์„ ํ•œ ๊ณณ์—์„œ ๊ด€๋ฆฌ.
โ€ข
๋ช…ํ™•ํ•œ ์‹๋ณ„์ž
๊ฒฐ์ œ์— MPTokenIssuanceID(๊ณ ์œ  ID)๋ฅผ ์‚ฌ์šฉ โ†’ ํ† ํฐ ์ •์˜๋ฅผ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„.
โ€ข
์Šค์ผ€์ผ(์†Œ์ˆ˜์ ) ๋‚ด์žฅ
AssetScale๋กœ ์ตœ์†Œ๋‹จ์œ„๋ฅผ ์ •์˜ โ†’ ๊ธˆ์•ก ์ฒ˜๋ฆฌ๊ฐ€ ์˜ˆ์ธก ๊ฐ€๋Šฅ.

3. ์‹œ๋‚˜๋ฆฌ์˜ค: createIssuance โ†’ authorizeHolder โ†’ sendMPT (+ setIssuance, destroyIssuance )

Step 1. ๋ฐœํ–‰ ์ •์˜ ์ƒ์„ฑ (createIssuance.ts)

โ€ข
์ฃผ์ฒด: ADMIN(๋ฐœํ–‰์ž)
โ€ข
ํ–‰๋™: MPTokenIssuanceCreate ํŠธ๋žœ์žญ์…˜ ์ „์†ก
โ€ข
๋‚ด์šฉ:
โ—ฆ
AssetScale(์†Œ์ˆ˜ ์ž๋ฆฌ์ˆ˜), MaximumAmount(์„ ํƒ), Flags( tfMPTCanTransfer, tfMPTRequireAuth ๋“ฑ) ์ง€์ •
โ—ฆ
โ€ข
tfMPTRequireAuth: true โ€“ ๋ฐœํ–‰์ž๊ฐ€ ์‚ฌ์ „ ์Šน์ธ(MPTokenAuthorize)ํ•œ ๊ณ„์ •๋งŒ ํ•ด๋‹น MPT๋ฅผ ๋ณด์œ ยท์ˆ˜๋ น ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ ๋ชจ๋“œ. KYC/AML ๋“ฑ ๊ทœ์ œ ์ค€์ˆ˜ํ˜• ํ† ํฐ์— ํ™œ์šฉ.
import { Client, Wallet, Transaction } from "xrpl" import path from "path" import dotenv from "dotenv" dotenv.config({ path: path.join(__dirname, "..", ".env") }) export async function createIssuance() { 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") const admin = Wallet.fromSeed(ADMIN_SEED) /** * MPTokenIssuanceCreate ํŠธ๋žœ์žญ์…˜ * - AssetScale: ์†Œ์ˆ˜ ์ž๋ฆฟ์ˆ˜ (0 โ†’ ์ •์ˆ˜๋งŒ) * - MaximumAmount: ์ด ๋ฐœํ–‰ ์ƒํ•œ (์˜ต์…˜) * - Flags: ์ •์ฑ… ์ง€์ • (์ „์†ก ๊ฐ€๋Šฅ, ์—์Šคํฌ๋กœ ๊ฐ€๋Šฅ, ๊ถŒํ•œ ํ•„์š” ์—ฌ๋ถ€ ๋“ฑ) */ const tx: Transaction = { TransactionType: "MPTokenIssuanceCreate", Account: admin.address, AssetScale: 0, // ์†Œ์ˆ˜์  ์—†์Œ MaximumAmount: "1000000000", // ์ตœ๋Œ€ ๋ฐœํ–‰๋Ÿ‰ (์˜ต์…˜) Flags: { // ์ •์ฑ… ์˜ˆ์‹œ tfMPTCanTransfer: true, // ์ „์†ก ๊ฐ€๋Šฅ tfMPTCanEscrow: true, // ์—์Šคํฌ๋กœ ๊ฐ€๋Šฅ tfMPTRequireAuth: false // ๊ถŒํ•œ ํ•„์š” X }, // MPTokenMetadata: "<hex-encoded string>" // ํ•„์š”์‹œ hex ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ } try { // ํŠธ๋žœ์žญ์…˜ ์ค€๋น„ โ†’ ์„œ๋ช… โ†’ ์ œ์ถœ 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)) // ๊ฒฐ๊ณผ ๋กœ๊ทธ์—์„œ ๋ฐœํ–‰๋ณธ์˜ IssuanceID ์ถ”์ถœ (์ผ๋ถ€ ๋…ธ๋“œ ๊ตฌํ˜„์ฒด๋Š” meta์— ์ €์žฅ๋จ) const issuanceId48 = (result.result.meta as any)?.mpt_issuance_id if (issuanceId48) { console.log(`IssuanceID(created): ${issuanceId48}`) } else { console.log("โš ๏ธ IssuanceID๋ฅผ meta์—์„œ ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์‘๋‹ต ๋กœ๊ทธ ํ™•์ธ ํ•„์š”.") } return result } finally { await client.disconnect() console.log("๐Ÿ”„ ์—ฐ๊ฒฐ ์ข…๋ฃŒ") } } // ์ง์ ‘ ์‹คํ–‰ if (require.main === module) { createIssuance().catch(e => { console.error(e); process.exit(1) }) }
TypeScript
๋ณต์‚ฌ
โ€ข
์ถœ๋ ฅ ์˜ˆ์‹œ
IssuanceID(created): 006419063CEBEB49FC20032206CE0F203138BFC59F1A####
PowerShell
๋ณต์‚ฌ
โ€ข
๊ฒฐ๊ณผ ๋กœ๊ทธ์—์„œ IssuanceID๋ฅผ ๋ณต์‚ฌ โ†’ ์ดํ›„ ๋ชจ๋“  ๋‹จ๊ณ„์— ์‚ฌ์šฉ

Step 2. ํ™€๋” ๊ถŒํ•œ ๋ถ€์—ฌ (authorizeHolder.ts)

โ€ข
์ฃผ์ฒด: ADMIN
โ€ข
ํ–‰๋™: MPTokenAuthorize ํŠธ๋žœ์žญ์…˜ ์ „์†ก
โ€ข
๋‚ด์šฉ:
โ—ฆ
๋ฐœํ–‰๋ณธ์ด tfMPTRequireAuth=true๋ฉด ์ „์†ก ์ „์— ํ™€๋”(USER)๋ฅผ ํ—ˆ๊ฐ€ํ•ด์•ผ ํ•จ
โ—ฆ
MPTokenIssuanceID: <๋ณต์‚ฌํ•œ ID>, Holder: USER.address
โ—ฆ
(ํ•ด์ œ๋Š” Flags.tfMPTUnauthorize)
1๋‹จ๊ณ„ : User๊ฐ€ Issuance์— ์˜ตํŠธ์ธ
โ€ข
Account : User ์ฃผ์†Œ
โ€ข
ํŠธ๋žœ์žญ์…˜ ์„œ๋ช… ์ฃผ์ฒด : User
import { Client, Wallet, Transaction } from "xrpl" import path from "path" import dotenv from "dotenv" dotenv.config({ path: path.join(__dirname, "..", ".env") }) // โš ๏ธ createIssuance ์‹คํ–‰ ๋กœ๊ทธ์—์„œ ๋ณต์‚ฌํ•œ IssuanceID ์‚ฌ์šฉ const ISSUANCE_ID = "0049CE349E4215DD8AC6196A0A5027DF489AEC3B17BD6211" export async function authorizeHolder() { const client = new Client("wss://s.devnet.rippletest.net:51233") await client.connect() const ADMIN_SEED = process.env.ADMIN_SEED const USER_SEED = process.env.USER2_SEED if (!ADMIN_SEED || !USER_SEED) throw new Error("Missing env: ADMIN_SEED, USER2_SEED") // ๋ฐœํ–‰์ž(Admin)์™€ ํ”ผ๋ฐœ๊ธ‰์ž(User) ์ง€๊ฐ‘ ๋กœ๋“œ const admin = Wallet.fromSeed(ADMIN_SEED) const user = Wallet.fromSeed(USER_SEED) /** * Step 1. User๊ฐ€ Issuance์— ์˜ตํŠธ์ธ * - Account: user.address * - ์„œ๋ช…์ž: User (์Šค์Šค๋กœ "์ฐธ์—ฌ ์˜์‚ฌ" ์ œ์ถœ) */ const tx: Transaction = { TransactionType: "MPTokenAuthorize", Account: user.address, // User๊ฐ€ ์„œ๋ช…/์ „์†ก MPTokenIssuanceID: ISSUANCE_ID, // MPT ๋ฐœํ–‰ ์ •์˜ ID // Holder: user.address // User ๋‹จ๊ณ„์—์„œ๋Š” ๋ถˆํ•„์š” // Flags: { tfMPTUnauthorize: true } // ํ•ด์ œํ•  ๋•Œ๋งŒ ์‚ฌ์šฉ } try { // ํŠธ๋žœ์žญ์…˜ ์ค€๋น„ โ†’ ์„œ๋ช… โ†’ ์ œ์ถœ const prepared = await client.autofill(tx) const signed = user.sign(prepared) const result = await client.submitAndWait(signed.tx_blob) // ์ „์ฒด ์‘๋‹ต ๋กœ๊ทธ ์ถœ๋ ฅ console.log(JSON.stringify(result, null, 2)) return result } finally { await client.disconnect() console.log("๐Ÿ”„ ์—ฐ๊ฒฐ ์ข…๋ฃŒ") } } // ์ง์ ‘ ์‹คํ–‰ if (require.main === module) { authorizeHolder().catch(e => { console.error(e); process.exit(1) }) }
TypeScript
๋ณต์‚ฌ
2๋‹จ๊ณ„ : Admin(๋ฐœํ–‰์ž)๊ฐ€ ํ—ˆ์šฉ
โ€ข
Account : Admin ์ฃผ์†Œ
โ€ข
Holder : User ์ฃผ์†Œ
โ€ข
ํŠธ๋žœ์žญ์…˜ ์„œ๋ช… ์ฃผ์ฒด : Admin
// createIssuance ์‹คํ–‰ ๋กœ๊ทธ์—์„œ ๋ณต์‚ฌํ•œ IssuanceID const ISSUANCE_ID = "006419063CEBEB49FC20032206CE0F203138BFC59F1A####" const tx: Transaction = { TransactionType: "MPTokenAuthorize", Account: admin.address, MPTokenIssuanceID: ISSUANCE_ID, Holder: user.address // Flags: { tfMPTUnauthorize: true } // ํ•ด์ œํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋งŒ ์‚ฌ์šฉ }
TypeScript
๋ณต์‚ฌ

Step 3. MPT ์ „์†ก (sendMPT.ts)

โ€ข
์ฃผ์ฒด: ADMIN(๋ณด๋‚ด๋Š” ์ชฝ)
โ€ข
ํ–‰๋™: Payment ํŠธ๋žœ์žญ์…˜ ์ „์†ก
โ€ข
๋‚ด์šฉ:
โ—ฆ
Amount๋Š” MPTAmount ํ˜•์‹:
{ mpt_issuance_id: "<๋ณต์‚ฌํ•œ ID>", value: "<์ •์ˆ˜ ๋ฌธ์ž์—ด>" }
โ—ฆ
v1์€ ์ง์ ‘ ๊ฒฐ์ œ๋งŒ ์ง€์›(DEX/๊ฒฝ๋กœํƒ์ƒ‰ ์—†์Œ)
import { Client, Wallet, Transaction } from "xrpl" import path from "path" import dotenv from "dotenv" dotenv.config({ path: path.join(__dirname, "..", ".env") }) // โš ๏ธ createIssuance ์‹คํ–‰ ๋กœ๊ทธ์—์„œ ๋ณต์‚ฌํ•œ IssuanceID ์ž…๋ ฅ const ISSUANCE_ID = "0049CE349E4215DD8AC6196A0A5027DF489AEC3B17BD6211" export async function sendMPT() { const client = new Client("wss://s.devnet.rippletest.net:51233") await client.connect() const ADMIN_SEED = process.env.ADMIN_SEED const USER_SEED = process.env.USER_SEED if (!ADMIN_SEED || !USER_SEED) throw new Error("Missing env: ADMIN_SEED, USER_SEED") const admin = Wallet.fromSeed(ADMIN_SEED) // ๋ฐœํ–‰์ž (์†ก์‹ ์ž) const user = Wallet.fromSeed(USER_SEED) // ์ˆ˜์‹ ์ž /** * MPT ์ „์†ก ํŠธ๋žœ์žญ์…˜ * - TransactionType: Payment * - Amount: { mpt_issuance_id, value } * * mpt_issuance_id: ๋ฐœํ–‰ ์ •์˜ ๊ณ ์œ  ID * * value: ์ „์†ก ์ˆ˜๋Ÿ‰ (์ •์ˆ˜ ๋ฌธ์ž์—ด) * - DeliverMax / SendMax ๋„ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ ์ง€์ • ๊ฐ€๋Šฅ */ const tx: Transaction = { TransactionType: "Payment", Account: admin.address, Destination: user.address, Amount: { mpt_issuance_id: ISSUANCE_ID, // ๋ฐœํ–‰๋ณธ ID value: "100" // ์ „์†ก ์ˆ˜๋Ÿ‰ } } try { // ํŠธ๋žœ์žญ์…˜ ์ค€๋น„ โ†’ ์„œ๋ช… โ†’ ์ œ์ถœ 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 } finally { await client.disconnect() console.log("๐Ÿ”„ ์—ฐ๊ฒฐ ์ข…๋ฃŒ") } } // ์ง์ ‘ ์‹คํ–‰ if (require.main === module) { sendMPT().catch(e => { console.error(e); process.exit(1) }) }
TypeScript
๋ณต์‚ฌ

(์ˆ˜์ •ํ•„์š”) Step 4. ๋ฐœํ–‰๋ณธ ๋ฝ/์–ธ๋ฝ (setIssuance.ts) + Clawback

โ€ข
์ฃผ์ฒด: ADMIN
โ€ข
ํ–‰๋™: MPTokenIssuanceSet ํŠธ๋žœ์žญ์…˜ ์ „์†ก
โ€ข
๋‚ด์šฉ:
โ—ฆ
๊ธ€๋กœ๋ฒŒ ์ž ๊ธˆ/ํ•ด์ œ: Flags.tfMPTLock / Flags.tfMPTUnlock
โ—ฆ
ํŠน์ • ํ™€๋”๋งŒ ์ž ๊ธˆ/ํ•ด์ œ: Holder์— ๋Œ€์ƒ ์ฃผ์†Œ ์ง€์ • + ๊ฐ™์€ ํ”Œ๋ž˜๊ทธ ์‚ฌ์šฉ
โ—ฆ
ํšจ๊ณผ: ์ž ๊ธˆ ์ค‘์—๋Š” ํ•ด๋‹น ๋ฒ”์œ„ ์ „์†ก/์‚ฌ์šฉ ์ œํ•œ(์ •์ฑ…์— ๋”ฐ๋ฆ„)
// createIssuance ์‹คํ–‰ ๋กœ๊ทธ์—์„œ ๋ณต์‚ฌํ•œ IssuanceID const ISSUANCE_ID = "006419063CEBEB49FC20032206CE0F203138BFC59F1A####" // ===== CLI ์ธ์ž ํŒŒ์‹ฑ ===== // ์‚ฌ์šฉ๋ฒ•: ts-node setIssuance.ts <lock|unlock> [holderAddress] // - ์ฒซ ๋ฒˆ์งธ ์ธ์ž(mode): "lock" ์ด๋ฉด ์ž ๊ธˆ, "unlock" ์ด๋ฉด ์ž ๊ธˆ ํ•ด์ œ // - ๋‘ ๋ฒˆ์งธ ์ธ์ž(holder): ์„ ํƒ๊ฐ’. ํŠน์ • ํ™€๋”๋งŒ ์ž ๊ทธ๊ฑฐ๋‚˜ ํ’€ ๋•Œ ๊ทธ XRPL ์ฃผ์†Œ๋ฅผ ๋„ฃ์Œ. // * holder๋ฅผ ์ƒ๋žตํ•˜๋ฉด "๊ธ€๋กœ๋ฒŒ" ์ ์šฉ(๋ฐœํ–‰๋ณธ ์ „์ฒด๋ฅผ ์ž ๊ทธ๊ฑฐ๋‚˜ ํ’‚). const mode = (process.argv[2] || "").toLowerCase() const holder = process.argv[3] // ์ธ์ž ๊ฒ€์ฆ: lock/unlock ์™ธ ๊ฐ’์ด๋ฉด ์‚ฌ์šฉ๋ฒ• ์•ˆ๋‚ด ํ›„ ์ข…๋ฃŒ(๋น„์ •์ƒ ์ข…๋ฃŒ ์ฝ”๋“œ 1) if (mode !== "lock" && mode !== "unlock") { console.error('Usage: ts-node setIssuance.ts <lock|unlock> [holderAddress]') process.exit(1) } // XRPL ํŠธ๋žœ์žญ์…˜ Flags ์„ค์ • // - MPTokenIssuanceSet๋Š” boolean ํ”Œ๋ž˜๊ทธ๋กœ ์„ค์ • ๊ฐ€๋Šฅ // * { tfMPTLock: true } -> ์ž ๊ธˆ // * { tfMPTUnlock: true } -> ์ž ๊ธˆ ํ•ด์ œ const flags = mode === "lock" ? { tfMPTLock: true } : { tfMPTUnlock: true } // ===== ํŠธ๋žœ์žญ์…˜ ๊ตฌ์„ฑ ===== const tx: Transaction = { TransactionType: "MPTokenIssuanceSet", Account: admin.address, // ๋ฐœํ–‰์ž(ADMIN) ์„œ๋ช…/์ „์†ก MPTokenIssuanceID: ISSUANCE_ID, // createIssuance ๊ฒฐ๊ณผ๋กœ ์–ป์€ ๋ฐœํ–‰ ์ •์˜ ID // Holder ํ•„๋“œ๋Š” ์„ ํƒ๊ฐ’: // - ํฌํ•จํ•˜๋ฉด "ํ•ด๋‹น ํ™€๋” ์ฃผ์†Œ๋งŒ" ๋Œ€์ƒ(๊ฐœ๋ณ„ ์ž ๊ธˆ/ํ•ด์ œ) // - ์ƒ๋žตํ•˜๋ฉด ๋ฐœํ–‰๋ณธ ์ „์ฒด ๋Œ€์ƒ(๊ธ€๋กœ๋ฒŒ ์ž ๊ธˆ/ํ•ด์ œ) ...(holder ? { Holder: holder } : {}), Flags: flags // ์œ„์—์„œ mode์— ๋”ฐ๋ผ lock/unlock ํ”Œ๋ž˜๊ทธ ์ง€์ • }
TypeScript
๋ณต์‚ฌ
โ€ข
์‚ฌ์šฉ ๋ฐฉ๋ฒ• : ํ„ฐ๋ฏธ๋„ ๋ช…๋ น์–ด ์˜ˆ์‹œ
# ๊ธ€๋กœ๋ฒŒ ์ž ๊ธˆ $npx ts-node setIssuance.ts lock # ๊ธ€๋กœ๋ฒŒ ์ž ๊ธˆ ํ•ด์ œ $npx ts-node setIssuance.ts unlock # ํŠน์ • ํ™€๋”(User)๋งŒ ์ž ๊ธˆ $npx ts-node setIssuance.ts lock <user ์ฃผ์†Œ> # ํŠน์ • ํ™€๋”(User)๋งŒ ์ž ๊ธˆ ํ•ด์ œ $npx ts-node setIssuance.ts unlock <user์ฃผ์†Œ>
Bash
๋ณต์‚ฌ

(์˜ต์…˜) Step 5. ๋ฐœํ–‰ ์ •์˜ ์‚ญ์ œ (destroyIssuance.ts)

โ€ข
์ฃผ์ฒด: ADMIN
โ€ข
ํ–‰๋™: MPTokenIssuanceDestroy ํŠธ๋žœ์žญ์…˜ ์ „์†ก
โ€ข
์„ฑ๊ณต ์กฐ๊ฑด: ๋ชจ๋“  ํ™€๋”์˜ ์ž”์•ก์ด 0์ด์–ด์•ผ ํ•จ(ํ•œ ๋ช…์ด๋ผ๋„ ๋‚จ์•„์žˆ์œผ๋ฉด ์‹คํŒจ)
โ€ข
ํšจ๊ณผ: ๋ฐœํ–‰ ์ •์˜ ์ œ๊ฑฐ, ๋ฆฌ์ €๋ธŒ 1 ๊ฐ์†Œ(์†Œ์œ  ์˜ค๋ธŒ์ ํŠธ ์ˆ˜ ๊ฐ์†Œ)
import { Client, Wallet, Transaction } from "xrpl" import path from "path" import dotenv from "dotenv" dotenv.config({ path: path.join(__dirname, "..", ".env") }) // โš ๏ธ createIssuance ์‹คํ–‰ ๋กœ๊ทธ์—์„œ ๋ฐœ๊ธ‰๋œ IssuanceID ์ž…๋ ฅ const ISSUANCE_ID = "0049CE349E4215DD8AC6196A0A5027DF489AEC3B17BD6211" export async function destroyIssuance() { 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") const admin = Wallet.fromSeed(ADMIN_SEED) /** * MPTokenIssuanceDestroy ํŠธ๋žœ์žญ์…˜ * - ๋ชจ๋“  ํ™€๋”๊ฐ€ ํ•ด๋‹น Issuance ์ž”์•ก์„ 0์œผ๋กœ ๋งŒ๋“ค์–ด์•ผ ์‹คํ–‰ ๊ฐ€๋Šฅ * - ์„ฑ๊ณต ์‹œ ๋ฐœํ–‰ ์ •์˜ ์ œ๊ฑฐ + ๋ฆฌ์ €๋ธŒ 1 ๊ฐ์†Œ */ const tx: Transaction = { TransactionType: "MPTokenIssuanceDestroy", Account: admin.address, // ๋ฐœํ–‰์ž(Admin) MPTokenIssuanceID: ISSUANCE_ID // ์‚ญ์ œํ•  ๋ฐœํ–‰๋ณธ ID } try { // ํŠธ๋žœ์žญ์…˜ ์ค€๋น„ โ†’ ์„œ๋ช… โ†’ ์ œ์ถœ 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 } finally { await client.disconnect() console.log("๐Ÿ”„ ์—ฐ๊ฒฐ ์ข…๋ฃŒ") } } // ์ง์ ‘ ์‹คํ–‰ if (require.main === module) { destroyIssuance().catch(e => { console.error(e); process.exit(1) }) }
TypeScript
๋ณต์‚ฌ