3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

LINE Blockchain APIでサービストークンを操作する

Last updated at Posted at 2022-09-19

はじめに

前回の続きです。LINE Blockchain Developers SDK for JavaScriptでサービストークンを取り扱ってみます。

前回のソースコードからAPI SECRETなどはdotenvに移行しました。

.envは以下のように記述します

.env
BASE_URL='https://test-api.blockchain.line.me'
SERVICE_API_KEY='[Your API Key]'
SERVICE_API_SECRET='[Your API Secret]'
OWNER_WALLET_ADDRESS='[Your Owner Wallet Address]'
OWNER_WALLET_SECRET='[Your Owner Wallet Secret]'

サービストークンを鋳造する

サービストークンを鋳造して指定のウォレットに発行します。まずは指定するウォレットの残高を確認しましょう。

src/index.ts
import * as dotenv from 'dotenv';
import * as devSdk from '@line/lbd-sdk-js';
import {
    ServiceToken,
    WalletResponse,
    MintServiceTokenRequest,
    TxHashResponse,
    ServiceTokenBalance
} from '@line/lbd-sdk-js';

dotenv.config();

const httpClient = new devSdk.HttpClient(
        process.env.BASE_URL as string,
        process.env.SERVICE_API_KEY as string,
        process.env.SERVICE_API_SECRET as string
    );

const getServiceToken = async (): Promise<ServiceToken> => {
  const srvs = await httpClient.serviceTokens();
  if (!srvs.responseData || srvs.responseData?.length < 1) throw new Error('No response data');
  const results = srvs.responseData;
  if (!results || results.length < 1) throw new Error('No service tokens');
  return results[0];
};

const getWallets = async (): Promise<WalletResponse[]> => {
  const wallets = await httpClient.wallets()
  if (!wallets.responseData || wallets.responseData?.length < 1) throw new Error('No response data');
  const result = wallets.responseData;
  if (!result) throw new Error('No wallet');
  return result;
};

const getWalletByName = (name: string, wallets: WalletResponse[]): WalletResponse|undefined => {
  return wallets.find((w) => { return w.name === name });
};

const getBalanceOfService = async (address: string, contructId: string): Promise<ServiceTokenBalance> => {
  const balance = await httpClient.serviceTokenBalanceOfWallet(address, contructId);
  if (!balance || !balance.responseData) throw new Error('No response data');
  const result = balance.responseData;
  if (!result) throw new Error('No balance data');
  return result;
};

const main = async () => {
  const st = await getServiceToken();
  const wallets = await getWallets();
  const wallet = getWalletByName('bathtimefish', wallets);
  if (!wallet) throw new Error('Wallet not found');
  const bal = await getBalanceOfService(wallet.walletAddress, st.contractId);
  console.log(bal);
};

main();

bathtimefishウォレットの残高は10000のようです

yarn run ts-node src/index.ts
{
  contractId: '[contruct ID]',
  name: 'BTFCoin',
  symbol: 'BTF',
  imgUri: '[image icon url]',
  decimals: 6,
  amount: '10000'
}

mintServiceToken()を追加してBTFCoinを1000鋳造してbathtimefishウォレットに発行します

src/index.ts
s dotenv from 'dotenv';
import * as devSdk from '@line/lbd-sdk-js';
import {
    ServiceToken,
    WalletResponse,
    MintServiceTokenRequest,
    TxHashResponse,
    ServiceTokenBalance
} from '@line/lbd-sdk-js';

dotenv.config();

const httpClient = new devSdk.HttpClient(
        process.env.BASE_URL as string,
        process.env.SERVICE_API_KEY as string,
        process.env.SERVICE_API_SECRET as string
    );

const getServiceToken = async (): Promise<ServiceToken> => {
  const srvs = await httpClient.serviceTokens();
  if (!srvs.responseData || srvs.responseData?.length < 1) throw new Error('No response data');
  const results = srvs.responseData;
  if (!results || results.length < 1) throw new Error('No service tokens');
  return results[0];
};

const mintServiceToken =async ( contructId: string, req: MintServiceTokenRequest): Promise<TxHashResponse> => {
  const res = await httpClient.mintServiceToken(contructId, req);
  const result = res.responseData;
  if (!result) throw new Error('Error');
  return result;
};

const getWallets = async (): Promise<WalletResponse[]> => {
  const wallets = await httpClient.wallets()
  if (!wallets.responseData || wallets.responseData?.length < 1) throw new Error('No response data');
  const result = wallets.responseData;
  if (!result) throw new Error('No wallet');
  return result;
};

const getWalletByName = (name: string, wallets: WalletResponse[]): WalletResponse|undefined => {
  return wallets.find((w) => { return w.name === name });
};

const getBalanceOfService = async (address: string, contructId: string): Promise<ServiceTokenBalance> => {
  const balance = await httpClient.serviceTokenBalanceOfWallet(address, contructId);
  if (!balance || !balance.responseData) throw new Error('No response data');
  const result = balance.responseData;
  if (!result) throw new Error('No balance data');
  return result;
};

const main = async () => {
  const st = await getServiceToken();
  console.log(st);
  const wallets = await getWallets();
  const wallet = getWalletByName('bathtimefish', wallets);
  if (!wallet) throw new Error('Wallet not found');
  const bal = await getBalanceOfService(wallet.walletAddress, st.contractId);
  console.log(bal);
  const mintRequest: MintServiceTokenRequest = {
    toAddress: wallet.walletAddress,
    amount: '1000',
    ownerAddress: process.env.OWNER_WALLET_ADDRESS as string,
    ownerSecret: process.env.OWNER_WALLET_SECRET as string,
  };
  const mintResult = await mintServiceToken(st.contractId, mintRequest);
  console.log(mintRequest);
};

main();

mintResultを確認すると正常に処理できた感じです

yarn run ts-node src/index.ts
{
  toAddress: '[To Wallet Address]',
  amount: '1000',
  ownerAddress: '[Owner Wallet Address]',
  ownerSecret: '[Owner Wallet Secret]'
}

結果は即時反映されないようなので、すこし経ってからもう一度残高を確認します

src/index.ts
import * as dotenv from 'dotenv';
import * as devSdk from '@line/lbd-sdk-js';
import {
    ServiceToken,
    WalletResponse,
    MintServiceTokenRequest,
    TxHashResponse,
    ServiceTokenBalance
} from '@line/lbd-sdk-js';

dotenv.config();

const httpClient = new devSdk.HttpClient(
        process.env.BASE_URL as string,
        process.env.SERVICE_API_KEY as string,
        process.env.SERVICE_API_SECRET as string
    );

const getServiceToken = async (): Promise<ServiceToken> => {
  const srvs = await httpClient.serviceTokens();
  if (!srvs.responseData || srvs.responseData?.length < 1) throw new Error('No response data');
  const results = srvs.responseData;
  if (!results || results.length < 1) throw new Error('No service tokens');
  return results[0];
};

const mintServiceToken =async ( contructId: string, req: MintServiceTokenRequest): Promise<TxHashResponse> => {
  const res = await httpClient.mintServiceToken(contructId, req);
  const result = res.responseData;
  if (!result) throw new Error('Error');
  return result;
};

const getWallets = async (): Promise<WalletResponse[]> => {
  const wallets = await httpClient.wallets()
  if (!wallets.responseData || wallets.responseData?.length < 1) throw new Error('No response data');
  const result = wallets.responseData;
  if (!result) throw new Error('No wallet');
  return result;
};

const getWalletByName = (name: string, wallets: WalletResponse[]): WalletResponse|undefined => {
  return wallets.find((w) => { return w.name === name });
};

const getBalanceOfService = async (address: string, contructId: string): Promise<ServiceTokenBalance> => {
  const balance = await httpClient.serviceTokenBalanceOfWallet(address, contructId);
  if (!balance || !balance.responseData) throw new Error('No response data');
  const result = balance.responseData;
  if (!result) throw new Error('No balance data');
  return result;
};

const main = async () => {
  const st = await getServiceToken();
  console.log(st);
  const wallets = await getWallets();
  const wallet = getWalletByName('bathtimefish', wallets);
  if (!wallet) throw new Error('Wallet not found');
  const bal = await getBalanceOfService(wallet.walletAddress, st.contractId);
  console.log(bal);
};

main();

残高が11000に増えました

yarn run ts-node src/index.ts
{
  contractId: '[contruct ID]',
  name: 'BTFCoin',
  symbol: 'BTF',
  imgUri: '[image icon url]',
  decimals: 6,
  amount: '11000'
}

サービストークンを転送する

サービストークンを他のウォレットに転送します。ここではあらかじめ転送先のAliceウォレットをLINE Blockchain Developersコンソールで作成しておきます

まず、Aliceウォレットの残高を確認します

src/index.ts
rt * as dotenv from 'dotenv';
import * as devSdk from '@line/lbd-sdk-js';
import {
    ServiceToken,
    WalletResponse,
    ServiceTokenBalance
} from '@line/lbd-sdk-js';

dotenv.config();

const httpClient = new devSdk.HttpClient(
        process.env.BASE_URL as string,
        process.env.SERVICE_API_KEY as string,
        process.env.SERVICE_API_SECRET as string
    );

const getServiceToken = async (): Promise<ServiceToken> => {
  const srvs = await httpClient.serviceTokens();
  if (!srvs.responseData || srvs.responseData?.length < 1) throw new Error('No response data');
  const results = srvs.responseData;
  if (!results || results.length < 1) throw new Error('No service tokens');
  return results[0];
};

const getWallets = async (): Promise<WalletResponse[]> => {
  const wallets = await httpClient.wallets()
  if (!wallets.responseData || wallets.responseData?.length < 1) throw new Error('No response data');
  const result = wallets.responseData;
  if (!result) throw new Error('No wallet');
  return result;
};

const getWalletByName = (name: string, wallets: WalletResponse[]): WalletResponse|undefined => {
  return wallets.find((w) => { return w.name === name });
};

const getBalanceOfService = async (address: string, contructId: string): Promise<ServiceTokenBalance> => {
  const balance = await httpClient.serviceTokenBalanceOfWallet(address, contructId);
  if (!balance || !balance.responseData) throw new Error('No response data');
  const result = balance.responseData;
  if (!result) throw new Error('No balance data');
  return result;
};

const main = async () => {
  const st = await getServiceToken();
  const wallets = await getWallets();
  const ownerWallet = getWalletByName('bathtimefish', wallets);
  const aliceWallet = getWalletByName('Alice', wallets);
  if (!ownerWallet) throw new Error('Wallet not found');
  if (!aliceWallet) throw new Error('Wallet not found');
  const bal = await getBalanceOfService(aliceWallet.walletAddress, st.contractId);
  console.log(bal);
};

main();

Aliceの残高は0です

yarn run ts-node src/index.ts
{
  contractId: '[contruct ID]',
  name: 'BTFCoin',
  symbol: 'BTF',
  imgUri: '[image icon url]',
  decimals: 6,
  amount: '0'
}

bathtimefishからAliceへサービストークン1000を転送します

src/index.ts
import * as dotenv from 'dotenv';
import * as devSdk from '@line/lbd-sdk-js';
import {
    ServiceToken,
    WalletResponse,
    ServiceTokenBalance,
    TransferServiceTokenRequest,
} from '@line/lbd-sdk-js';

dotenv.config();

const httpClient = new devSdk.HttpClient(
        process.env.BASE_URL as string,
        process.env.SERVICE_API_KEY as string,
        process.env.SERVICE_API_SECRET as string
    );

const getServiceToken = async (): Promise<ServiceToken> => {
  const srvs = await httpClient.serviceTokens();
  if (!srvs.responseData || srvs.responseData?.length < 1) throw new Error('No response data');
  const results = srvs.responseData;
  if (!results || results.length < 1) throw new Error('No service tokens');
  return results[0];
};

const getWallets = async (): Promise<WalletResponse[]> => {
  const wallets = await httpClient.wallets()
  if (!wallets.responseData || wallets.responseData?.length < 1) throw new Error('No response data');
  const result = wallets.responseData;
  if (!result) throw new Error('No wallet');
  return result;
};

const getWalletByName = (name: string, wallets: WalletResponse[]): WalletResponse|undefined => {
  return wallets.find((w) => { return w.name === name });
};

const getBalanceOfService = async (address: string, contructId: string): Promise<ServiceTokenBalance> => {
  const balance = await httpClient.serviceTokenBalanceOfWallet(address, contructId);
  if (!balance || !balance.responseData) throw new Error('No response data');
  const result = balance.responseData;
  if (!result) throw new Error('No balance data');
  return result;
};

const transferServiceToken = async (walletAddress: string, contractId: string, request: TransferServiceTokenRequest) => {
  const res = await httpClient.transferServiceTokenOfWallet(walletAddress, contractId, request);
  if (!res || !res.responseData) throw new Error('No response data');
  const result = res.responseData;
  if (!result) throw new Error('No balance data');
  return result;
}

const main = async () => {
  const st = await getServiceToken();
  const wallets = await getWallets();
  const ownerWallet = getWalletByName('bathtimefish', wallets);
  const aliceWallet = getWalletByName('Alice', wallets);
  if (!ownerWallet) throw new Error('Wallet not found');
  if (!aliceWallet) throw new Error('Wallet not found');
  const transferRequest: TransferServiceTokenRequest = {
    walletSecret: process.env.OWNER_WALLET_SECRET as string,
    toAddress: aliceWallet.walletAddress,
    amount: '1000',
  };
  const transferResult = await transferServiceToken(ownerWallet.walletAddress, st.contractId, transferRequest);
  console.log(transferRequest);

main();

転送できたようです

yarn run ts-node src/index.ts
{
  walletSecret: '[Wallet Secret]',
  toAddress: '[To Wallet Address]',
  amount: '1000'
}

結果は即時反映されないようなので、すこし経ってからもう一度残高を確認します

src/index.ts
import * as dotenv from 'dotenv';
import * as devSdk from '@line/lbd-sdk-js';
import {
    ServiceToken,
    WalletResponse,
    ServiceTokenBalance,
    TransferServiceTokenRequest,
} from '@line/lbd-sdk-js';

dotenv.config();

const httpClient = new devSdk.HttpClient(
        process.env.BASE_URL as string,
        process.env.SERVICE_API_KEY as string,
        process.env.SERVICE_API_SECRET as string
    );

const getServiceToken = async (): Promise<ServiceToken> => {
  const srvs = await httpClient.serviceTokens();
  if (!srvs.responseData || srvs.responseData?.length < 1) throw new Error('No response data');
  const results = srvs.responseData;
  if (!results || results.length < 1) throw new Error('No service tokens');
  return results[0];
};

const getWallets = async (): Promise<WalletResponse[]> => {
  const wallets = await httpClient.wallets()
  if (!wallets.responseData || wallets.responseData?.length < 1) throw new Error('No response data');
  const result = wallets.responseData;
  if (!result) throw new Error('No wallet');
  return result;
};

const getWalletByName = (name: string, wallets: WalletResponse[]): WalletResponse|undefined => {
  return wallets.find((w) => { return w.name === name });
};

const getBalanceOfService = async (address: string, contructId: string): Promise<ServiceTokenBalance> => {
  const balance = await httpClient.serviceTokenBalanceOfWallet(address, contructId);
  if (!balance || !balance.responseData) throw new Error('No response data');
  const result = balance.responseData;
  if (!result) throw new Error('No balance data');
  return result;
};

const main = async () => {
  const st = await getServiceToken();
  const wallets = await getWallets();
  const ownerWallet = getWalletByName('bathtimefish', wallets);
  const aliceWallet = getWalletByName('Alice', wallets);
  if (!ownerWallet) throw new Error('Wallet not found');
  if (!aliceWallet) throw new Error('Wallet not found');
  const bal = await getBalanceOfService(aliceWallet.walletAddress, st.contractId);
  console.log(bal);
};

main();

残高が増えました

{
  contractId: '[contruct ID]',
  name: 'BTFCoin',
  symbol: 'BTF',
  imgUri: '[image icon url]',
  decimals: 6,
  amount: '1000'
}

サービストークンを焼却する

指定したウォレットのサービストークンを焼却します。bathtimefishのトークンを1000焼却します

src/index.ts
import * as dotenv from 'dotenv';
import * as devSdk from '@line/lbd-sdk-js';
import {
    ServiceToken,
    WalletResponse,
    ServiceTokenBalance,
    BurnFromServiceTokenRequest,
    TxHashResponse,
} from '@line/lbd-sdk-js';

dotenv.config();

const httpClient = new devSdk.HttpClient(
        process.env.BASE_URL as string,
        process.env.SERVICE_API_KEY as string,
        process.env.SERVICE_API_SECRET as string
    );

const getServiceToken = async (): Promise<ServiceToken> => {
  const srvs = await httpClient.serviceTokens();
  if (!srvs.responseData || srvs.responseData?.length < 1) throw new Error('No response data');
  const results = srvs.responseData;
  if (!results || results.length < 1) throw new Error('No service tokens');
  return results[0];
};

const getWallets = async (): Promise<WalletResponse[]> => {
  const wallets = await httpClient.wallets()
  if (!wallets.responseData || wallets.responseData?.length < 1) throw new Error('No response data');
  const result = wallets.responseData;
  if (!result) throw new Error('No wallet');
  return result;
};

const getWalletByName = (name: string, wallets: WalletResponse[]): WalletResponse|undefined => {
  return wallets.find((w) => { return w.name === name });
};

const getBalanceOfService = async (address: string, contructId: string): Promise<ServiceTokenBalance> => {
  const balance = await httpClient.serviceTokenBalanceOfWallet(address, contructId);
  if (!balance || !balance.responseData) throw new Error('No response data');
  const result = balance.responseData;
  if (!result) throw new Error('No balance data');
  return result;
};

const burnServiceToken = async (contractId: string, request: BurnFromServiceTokenRequest): Promise<TxHashResponse> => {
  const res = await httpClient.burnFromServiceToken(contractId, request);
  if (!res || !res.responseData) throw new Error('No response data');
  const result = res.responseData;
  if (!result) throw new Error('No data');
  return result;
}

const main = async () => {
  const st = await getServiceToken();
  const wallets = await getWallets();
  const wallet = getWalletByName('bathtimefish', wallets);
  if (!wallet) throw new Error('Wallet not found');
  const burnRequest: BurnFromServiceTokenRequest = {
    fromAddress: wallet.walletAddress,
    amount: '1000',
    ownerAddress: process.env.OWNER_WALLET_ADDRESS as string,
    ownerSecret: process.env.OWNER_WALLET_SECRET as string,
  };
  const burnResult = await burnServiceToken(st.contractId, burnRequest);
  console.log(burnRequest);
};

main();

焼却できたようです

{
  fromAddress: '[From Wallet Address]',
  amount: '1000',
  ownerAddress: '[Owner Wallet Address]',
  ownerSecret: '[Owner Wallet Secret]'
}

結果は即時反映されないようなので、すこし経ってからもう一度残高を確認します

src/index.ts
import * as dotenv from 'dotenv';
import * as devSdk from '@line/lbd-sdk-js';
import {
    ServiceToken,
    WalletResponse,
    ServiceTokenBalance,
    BurnFromServiceTokenRequest,
    TxHashResponse,
} from '@line/lbd-sdk-js';

dotenv.config();

const httpClient = new devSdk.HttpClient(
        process.env.BASE_URL as string,
        process.env.SERVICE_API_KEY as string,
        process.env.SERVICE_API_SECRET as string
    );

const getServiceToken = async (): Promise<ServiceToken> => {
  const srvs = await httpClient.serviceTokens();
  if (!srvs.responseData || srvs.responseData?.length < 1) throw new Error('No response data');
  const results = srvs.responseData;
  if (!results || results.length < 1) throw new Error('No service tokens');
  return results[0];
};

const getWallets = async (): Promise<WalletResponse[]> => {
  const wallets = await httpClient.wallets()
  if (!wallets.responseData || wallets.responseData?.length < 1) throw new Error('No response data');
  const result = wallets.responseData;
  if (!result) throw new Error('No wallet');
  return result;
};

const getWalletByName = (name: string, wallets: WalletResponse[]): WalletResponse|undefined => {
  return wallets.find((w) => { return w.name === name });
};

const getBalanceOfService = async (address: string, contructId: string): Promise<ServiceTokenBalance> => {
  const balance = await httpClient.serviceTokenBalanceOfWallet(address, contructId);
  if (!balance || !balance.responseData) throw new Error('No response data');
  const result = balance.responseData;
  if (!result) throw new Error('No balance data');
  return result;
};

const burnServiceToken = async (contractId: string, request: BurnFromServiceTokenRequest): Promise<TxHashResponse> => {
  const res = await httpClient.burnFromServiceToken(contractId, request);
  if (!res || !res.responseData) throw new Error('No response data');
  const result = res.responseData;
  if (!result) throw new Error('No data');
  return result;
}

const main = async () => {
  const st = await getServiceToken();
  const wallets = await getWallets();
  const wallet = getWalletByName('bathtimefish', wallets);
  if (!wallet) throw new Error('Wallet not found');
  const bal = await getBalanceOfService(wallet.walletAddress, st.contractId);
  console.log(bal);
};

main();

残高が減りました

{
  contractId: '[contruct ID]',
  name: 'BTFCoin',
  symbol: 'BTF',
  imgUri: '[image icon url]',
  decimals: 6,
  amount: '9000'
}

おわりに

サービストークンはERC-20規格に似ているため仮想通貨のようなものを作ることができます。LINE BrockchainのJavaScript SDKを使って上記のように簡単に扱うことができるので仮想通貨を初学者は勉強に使のもいいかもしれません。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?