데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      OpenLab 2기 - 누구나 하는 Smart Contract 개발 6회차 모임

      whitefes 24.11.25
      249 4 0
      DEVOTEE 요약
      Smart Contract OpenLab 스터디 2기에서 Solana와 Web3에 대해 배우고, 스터디 구성원들과 지식을 교류했습니다. 마지막 모임에서는 Token Accounts 관리 방법, 토큰 위임 및 사용 철회 방법 등을 발표했습니다. 다음 기회에 스터디에 관심 있는 분들은 열정과 함께 참여하여 많은 것을 배울 수 있을 것이라 기대합니다.
      DEVOTEE 추천 블로그

      누구나 하는 Smart Contract OpenLab 스터디 2기에 참여 중인 백철승입니다.


      처음 모여서 스터디 계획을 세운게 엊그제 같은데 벌써 마지막 모임이라니 아쉬움이 많이 남습니다.


      Solana는 물론 Web3에 대해서 아무것도 몰랐었는데 다른 스터디 구성원 분들이 모르는 부분을 많이 채워주고 또 질문에 대해서 친절하게 답변을 해주어 이제는 조금 많이 친해진 것 같습니다.


      다음 번에 3기가 진행이 된다면 관심 있는 분들은 열정만 가지고 계신다면 스스로 참여하면서 배우고 또 다른 분들과의 지식 교류를 통해 많은 것을 배워갈 수 있을 것이라고 생각합니다.


      모임에 앞서 12월 6일에 있을 데보션 테크 데이에 발표자로 나설 구정태님이 발표 주제에 대해서 설명을 해주셨습니다.

      어떻게 해야 세션에 참가하신 분들에게 도움이 될까 많은 고민을 하고 계셨고 준비 또한 열심히 하고 계셨습니다.

      발표 당일 저희 모임을 대표해서 발표하실 구정태님이 준비해주신 내용 기대해주시고 또 많은 박수 부탁드립니다.

      20241121_191628.jpg

      마지막 모임에는 백철승, 김상현 두 분께서 발표를 진행하셨고 각각 다음의 주제를 준비해주셨습니다.


      백철승

      • 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


      How to Close Token Accounts

      먼저 Token Accounts를 닫는 경우에 대한 발표로 시작되었습니다.

      Token Accounts를 닫는 방법 그리고 닫아야하는 이유에 대한 설명과 wrapped token에 대한 설명이 이루어졌습니다.

      스터디 자료에는 나와 있지 않지만 wrapped token을 사용하는 이유와 실제 사례에 대한 토론도 이루어 졌습니다.

      image.png

      image.png

      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 */,
            ])}`,
          );
        }
      })();


      How to Set Authority on Token Accounts or Mints

      다음으로 이어진 발표는 Token Accounts와 Mints에 권한을 부여하는 방법입니다.

      아무래도 cookbook의 예제 코드 만으로는 이해가 안되는 부분들이 있어 왜 사용 하는지에 대한 부분을 준비했습니다.

      image.png

      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 */,
            ])}`,
          );
        }
      })();


      How to Delegate Token Accounts

      마지막으로 Token Accounts에 대한 위임입니다.

      image.png

      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 */,
            ])}`,
          );
        }
      })();


      이어서 김상현님이 발표를 진행해주셨습니다.

      How to Revoke a Token Delegate

      앞에 토큰 사용 권한 위임에 대해서 더 자세하게 조사하여 설명을 해주셨습니다.

      토큰 소유자가 다른 주소에게 자신의 토큰 사용 권한을 임시로 위임했던 것을 취소하는 것을

      의미합니다.


      위임의 실제 사용 사례:

      • 판매자가 NFT 판매 등록

        1. 마켓플레이스가 NFT 전송 권한을 위임받음

        2. 구매자가 나타나면 마켓플레이스가 NFT 전송

      • DEX

        1. 트레이더가 100 USDC 거래 주문

        2. DEX가 100 USDC의 전송 권한을 위임받음

        3. 거래 성사되면 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 */,
            ])}`,
          );
        }
      })();


      How to Use Wrapped SOL

      앞에 주제와 겹치는 부분이 있었지만 실제 사례를 곁들여 좀 더 자세하고 쉽게 설명해주셨습니다.


      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,
      );
      })();


      How to Get All Token Accounts by Autority

      마지막으로 권한을 통해 모든 토큰의 정보를 가져오는 것이고 이 부분은 코드를 돌려본 결과를 설명하며 마무리 했습니다.

      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("====================");
          });
      })();

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      whitefes 님의 최신 블로그

      더보기

      DEVOTEE 추천 블로그

      동영상 기고하기