23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
누구나 하는 Smart Contract OpenLab 스터디 2기에 참여 중인 백철승입니다.
처음 모여서 스터디 계획을 세운게 엊그제 같은데 벌써 마지막 모임이라니 아쉬움이 많이 남습니다.
Solana는 물론 Web3에 대해서 아무것도 몰랐었는데 다른 스터디 구성원 분들이 모르는 부분을 많이 채워주고 또 질문에 대해서 친절하게 답변을 해주어 이제는 조금 많이 친해진 것 같습니다.
다음 번에 3기가 진행이 된다면 관심 있는 분들은 열정만 가지고 계신다면 스스로 참여하면서 배우고 또 다른 분들과의 지식 교류를 통해 많은 것을 배워갈 수 있을 것이라고 생각합니다.
모임에 앞서 12월 6일에 있을 데보션 테크 데이에 발표자로 나설 구정태님이 발표 주제에 대해서 설명을 해주셨습니다.
어떻게 해야 세션에 참가하신 분들에게 도움이 될까 많은 고민을 하고 계셨고 준비 또한 열심히 하고 계셨습니다.
발표 당일 저희 모임을 대표해서 발표하실 구정태님이 준비해주신 내용 기대해주시고 또 많은 박수 부탁드립니다.
마지막 모임에는 백철승, 김상현 두 분께서 발표를 진행하셨고 각각 다음의 주제를 준비해주셨습니다.
백철승
How to Close Token Accounts
How to Set Authority on Token Accounts or Mints
How to Delegate Token Accounts
김상현
How to Revoke a Token Delegate
How to Use Wrapped SOL
How to Get All Token Accounts by Autority
먼저 Token Accounts를 닫는 경우에 대한 발표로 시작되었습니다.
Token Accounts를 닫는 방법 그리고 닫아야하는 이유에 대한 설명과 wrapped token에 대한 설명이 이루어졌습니다.
스터디 자료에는 나와 있지 않지만 wrapped token을 사용하는 이유와 실제 사례에 대한 토론도 이루어 졌습니다.
import {
clusterApiUrl,
Connection,
PublicKey,
Keypair,
Transaction,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import { closeAccount, createCloseAccountInstruction } from "@solana/spl-token";
import bs58 from "bs58";
(async () => {
// connection
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
// 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
const feePayer = Keypair.fromSecretKey(
bs58.decode(
"588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2",
),
);
// G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
const alice = Keypair.fromSecretKey(
bs58.decode(
"4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp",
),
);
const tokenAccountPubkey = new PublicKey(
"2XYiFjmU1pCXmC2QfEAghk6S7UADseupkNQdnRBXszD5",
);
// 1) use build-in function
{
let txhash = await closeAccount(
connection, // connection
feePayer, // payer
tokenAccountPubkey, // token account which you want to close
alice.publicKey, // destination
alice, // owner of token account
);
console.log(`txhash: ${txhash}`);
}
// or
// 2) compose by yourself
{
let tx = new Transaction().add(
createCloseAccountInstruction(
tokenAccountPubkey, // token account which you want to close
alice.publicKey, // destination
alice.publicKey, // owner of token account
),
);
console.log(
`txhash: ${await sendAndConfirmTransaction(connection, tx, [
feePayer,
alice /* fee payer + owner */,
])}`,
);
}
})();다음으로 이어진 발표는 Token Accounts와 Mints에 권한을 부여하는 방법입니다.
아무래도 cookbook의 예제 코드 만으로는 이해가 안되는 부분들이 있어 왜 사용 하는지에 대한 부분을 준비했습니다.
import {
clusterApiUrl,
Connection,
PublicKey,
Keypair,
Transaction,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import {
AuthorityType,
createSetAuthorityInstruction,
setAuthority,
} from "@solana/spl-token";
import bs58 from "bs58";
(async () => {
// connection
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
// 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
const feePayer = Keypair.fromSecretKey(
bs58.decode(
"588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2",
),
);
// G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
const alice = Keypair.fromSecretKey(
bs58.decode(
"4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp",
),
);
const randomGuy = Keypair.generate();
console.log(`random guy: ${randomGuy.publicKey.toBase58()}`);
const mintPubkey = new PublicKey(
"8mAKLjGGmjKTnmcXeyr3pr7iX13xXVjJJiL6RujDbSPV",
);
// authority type
// 1) for mint account
// AuthorityType.MintTokens
// AuthorityType.FreezeAccount
// 2) for token account
// AuthorityType.AccountOwner
// AuthorityType.CloseAccount
// 1) use build-in function
{
let txhash = await setAuthority(
connection, // connection
feePayer, // payer
mintPubkey, // mint account || token account
alice, // current authority
AuthorityType.MintTokens, // authority type
randomGuy.publicKey, // new authority (you can pass `null` to close it)
);
console.log(`txhash: ${txhash}`);
}
// or
// 2) compose by yourself
{
let tx = new Transaction().add(
createSetAuthorityInstruction(
mintPubkey, // mint acocunt || token account
alice.publicKey, // current auth
AuthorityType.MintTokens, // authority type
feePayer.publicKey, // new auth (you can pass `null` to close it)
),
);
console.log(
`txhash: ${await sendAndConfirmTransaction(connection, tx, [
feePayer,
alice /* fee payer + origin auth */,
])}`,
);
}
})();마지막으로 Token Accounts에 대한 위임입니다.
import {
clusterApiUrl,
Connection,
PublicKey,
Keypair,
Transaction,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import {
approveChecked,
createApproveCheckedInstruction,
} from "@solana/spl-token";
import bs58 from "bs58";
(async () => {
// connection
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
// 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
const feePayer = Keypair.fromSecretKey(
bs58.decode(
"588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2",
),
);
// G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
const alice = Keypair.fromSecretKey(
bs58.decode(
"4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp",
),
);
const randomGuy = Keypair.generate();
const mintPubkey = new PublicKey(
"8mAKLjGGmjKTnmcXeyr3pr7iX13xXVjJJiL6RujDbSPV",
);
const tokenAccountPubkey = new PublicKey(
"GMxZfDmpR1b3vdJYXHzdF5noVLQogZuUAsDHHQ3ytPfV",
);
// 1) use build-in function
{
let txhash = await approveChecked(
connection, // connection
feePayer, // fee payer
mintPubkey, // mint
tokenAccountPubkey, // token account
randomGuy.publicKey, // delegate
alice, // owner of token account
1e8, // amount, if your deciamls is 8, 10^8 for 1 token
8, // decimals
);
console.log(`txhash: ${txhash}`);
}
// or
// 2) compose by yourself
{
let tx = new Transaction().add(
createApproveCheckedInstruction(
tokenAccountPubkey, // token account
mintPubkey, // mint
randomGuy.publicKey, // delegate
alice.publicKey, // owner of token account
1e8, // amount, if your deciamls is 8, 10^8 for 1 token
8, // decimals
),
);
console.log(
`txhash: ${await sendAndConfirmTransaction(connection, tx, [
feePayer,
alice /* fee payer + owner */,
])}`,
);
}
})();이어서 김상현님이 발표를 진행해주셨습니다.
앞에 토큰 사용 권한 위임에 대해서 더 자세하게 조사하여 설명을 해주셨습니다.
토큰 소유자가 다른 주소에게 자신의 토큰 사용 권한을 임시로 위임했던 것을 취소하는 것을
의미합니다.
위임의 실제 사용 사례:
판매자가 NFT 판매 등록
마켓플레이스가 NFT 전송 권한을 위임받음
구매자가 나타나면 마켓플레이스가 NFT 전송
DEX
트레이더가 100 USDC 거래 주문
DEX가 100 USDC의 전송 권한을 위임받음
거래 성사되면 DEX가 USDC 전송
import {
clusterApiUrl,
Connection,
PublicKey,
Keypair,
Transaction,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import { createRevokeInstruction, revoke } from "@solana/spl-token";
import bs58 from "bs58";
(async () => {
// connection
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
// 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
const feePayer = Keypair.fromSecretKey(
bs58.decode(
"588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2",
),
);
// G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
const alice = Keypair.fromSecretKey(
bs58.decode(
"4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp",
),
);
const tokenAccountPubkey = new PublicKey(
"DRS5CSgPQp4uvPPcUA34tckfYFNUPNBJi77fVbnSfQHr",
);
// 1) use build-in function
{
let txhash = await revoke(
connection, // connection
feePayer, // payer
tokenAccountPubkey, // token account
alice, // owner of token account
);
console.log(`txhash: ${txhash}`);
}
// or
// 2) compose by yourself
{
let tx = new Transaction().add(
createRevokeInstruction(
tokenAccountPubkey, // token account
alice.publicKey, // owner of token account
),
);
console.log(
`txhash: ${await sendAndConfirmTransaction(connection, tx, [
feePayer,
alice /* fee payer + origin auth */,
])}`,
);
}
})();앞에 주제와 겹치는 부분이 있었지만 실제 사례를 곁들여 좀 더 자세하고 쉽게 설명해주셨습니다.
Wrapped SOL (wSOL은 일반 SOL을 SPL 토큰 형태로 변환한 것입니다. 일반 SOL은
SPL 토큰이 아니라서 다른 SPL 토큰들과 호환되지 않습니다. DEX나 DeFi 프로토콜에
서 SOL을 사용하려면 wSOL 형태로 변환해야 합니다
실제 사례 (WBTC)
비트코인을 토큰화해서 이더리움에서 사용 가능합니다.
관리자에서 BTC를 전송하고 그 가치만큼의 ERC-20 토큰인 WBTC 민팅합니다.
WBTC를 다시 BTC로 바꿀경우 WBTC를 BTC만큼 소각합니다.
블록체인 간의 상호 운용 가능하게 해주지만 중간 관리자에게
코인을 전송해야되는 리스크가 존재합니다.
import {
clusterApiUrl,
Connection,
Keypair,
Transaction,
SystemProgram,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import {
NATIVE_MINT,
getAssociatedTokenAddress,
createSyncNativeInstruction,
} from "@solana/spl-token";
import bs58 from "bs58";
(async () => {
// connection
const connection = new Connection(clusterApiUrl("devnet")
// 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
const feePayer = Keypair.fromSecretKey(
bs58.decode(
"588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr8
),
);
// G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
const alice = Keypair.fromSecretKey(
bs58.decode(
"4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgF
),
);
// remember to create ATA first
let ata = await getAssociatedTokenAddress(
NATIVE_MINT, // mint
alice.publicKey, // owner
);
let amount = 1 * 1e9; /* Wrapped SOL's decimals is 9 */
let tx = new Transaction().add(
// trasnfer SOL
SystemProgram.transfer({
fromPubkey: alice.publicKey,
toPubkey: ata,
lamports: amount,
}),
// sync wrapped SOL balance
createSyncNativeInstruction(ata),
);
console.log(
`txhash: ${await sendAndConfirmTransaction(connection,
);
})();마지막으로 권한을 통해 모든 토큰의 정보를 가져오는 것이고 이 부분은 코드를 돌려본 결과를 설명하며 마무리 했습니다.
import { clusterApiUrl, Connection, PublicKey } from "@solana/
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
(async () => {
// connection
const connection = new Connection(clusterApiUrl("devnet"),
const owner = new PublicKey("G2FAbFQPFa5qKXCetoFZQEvF9BVvCK
let response = await connection.getParsedTokenAccountsByOwne
programId: TOKEN_PROGRAM_ID,
});
response.value.forEach(accountInfo => {
console.log(`pubkey: ${accountInfo.pubkey.toBase58()}`);
console.log(`mint: ${accountInfo.account.data["parsed"]["i
console.log(
`owner: ${accountInfo.account.data["parsed"]["info"]["ow
);
console.log(
`decimals: ${accountInfo.account.data["parsed"]["info"]
);
console.log(
`amount: ${accountInfo.account.data["parsed"]["info"]["
);
console.log("====================");
});
})();
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.