암호화폐 지갑은 블록체인에서 자금에 액세스하고 관리할 수 있는 인터페이스입니다.
보유하고 있는 암호화폐의 양을 보여주며 블록체인과 통신하여 디지털 자산을 주고 받을 수 있습니다.
암호화폐 거래, DeFi 플랫폼 또는 NFT를 이용하려면 암호화 지갑이 필요합니다.
이번 튜토리얼에서는 BLOCKSDK API, Next.js 프레임워크, 암호화폐 지갑을 생성합니다.
git clone https://github.com/Block-Chen/nextjs_wallet_demo.git
BLOCKSDK 홈페이지에 회원가입하여 WEB3 API 토큰 발급
├── src/app
├── api //api 목록
│ └── wallet
│ ├── balance
│ ├── create
│ ├── erc20
│ ├── erc721
│ ├── erc1155
│ └── list
├── wallet //페이지 목록
│ ├── balance
│ ├── create
│ ├── send
│ └── page.tsx
└── page.tsx
npm i && npm run dev
npm run build : Nextjs 어플리케이션을 빌드한다.
npm run start : build로 생성된 빌드 파일을 사용하여 어플리케이션을 실행한다.
npm run dev : Next.js 애플리케이션을 개발 환경에서 실행한다.
개발 모드에서는 페이지가 변경될 때마다 자동으로 빌드되어 브라우저에서 새로고침된다.
또한 정적 파일들이 요청될 때마다 다시 생성되어 더 빠른 개발을 가능하게 한다.
NEXT_PUBLIC_BLOCKSDK_TOKEN // blocksdk api 토큰
NEXT_PUBLIC_URL // WEB3 테스트넷 or 메인넷 엔드포인트
NEXT_PUBLIC_NET // 사용할 메인넷(eth,bsc,klay,matic)
생성할 지갑 이름을 입력하고 데이터를 전송하면 json형식으로 api에 전송합니다.
지갑 이름은 생성한 지갑 리스트에서 쉬운 구분을 위해 사용됩니다.
// /app/wallet/page.tsx
async function onSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault()
setIsLoading(true)
setError(null) // Clear previous errors when a new request starts
try {
//body.name으로 지갑 이름 전달
const response = await fetch('/api/wallet/create' , {
method: 'POST',
body: JSON.stringify({
name : body.name,
}),
}).then(response=>response.json()).then(data=>setData(data.data))
} catch (error : any) {
// Capture the error message to display to the user
setError(error.message)
console.error(error)
} finally {
setIsLoading(false)
}
}
지갑 생성 api에서 json형태로 받은 지갑이름을 가지고 BLOCKSDK API를 활용해 암호화폐 지갑을 생성합니다.
지갑 생성시 반환된 privatekey는 생성시에만 반환되니 저장해두셔야합니다.
당사에서는 privatekey를 저장하지 않으며 복구해드리지 않습니다.
// /app/api/wallet/create/route.tsx
import { NextResponse, NextRequest } from 'next/server';
//지갑 생성
export async function POST(request : NextRequest) {
const { searchParams } = new URL(request.url)
//.env에 설정한 정보를 호출
const api_token = process.env.NEXT_PUBLIC_BLOCKSDK_TOKEN
const url = process.env.NEXT_PUBLIC_URL as string
const net = process.env.NEXT_PUBLIC_NET
const payload = await request.json()
const name = payload.get('name')
//지갑 생성 API
const res = await fetch(url + net + `/address?api_token=` + api_token, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: name }),
})
const data = await res.json()
return NextResponse.json({data})
}
지갑 생성을 통해 자신이 생성한 지갑목록을 확인할 수 있습니다.
지갑 생성과는 다르게 private_key가 반환되지 않습니다.
// /app/wallet/create/page.tsx
async function onSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault()
setIsLoading(true)
setError(null) // Clear previous errors when a new request starts
try {
const formData = new FormData(event.currentTarget)
//생성 지갑목록 호출
const response = await fetch('/api/wallet/list' , {
method: 'GET',
}).then(response=>response.json()).then(data=>setData(data.data))
} catch (error : any) {
// Capture the error message to display to the user
setError(error.message)
console.error(error)
} finally {
setIsLoading(false)
}
}
.env에서 설정한 BLOCKSDK_TOKEN값을 이용하여 생성한 지갑 리스트가 반환됩니다.
// /app/api/wallet/list/route.tsx
import { NextResponse, NextRequest } from 'next/server';
//지갑 리스트
export async function GET(request : NextRequest) {
const { searchParams } = new URL(request.url)
const api_token = process.env.NEXT_PUBLIC_BLOCKSDK_TOKEN
const url = process.env.NEXT_PUBLIC_URL as string
const net = process.env.NEXT_PUBLIC_NET
//생성한 지갑목록 호출
const res = await fetch(url + net + `/address?api_token=` + api_token, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
const data = await res.json();
return NextResponse.json({ data })
}
지갑의 소유중 코인을 확인할 수 있습니다.
메인넷 코인, erc20, nft에 대한 정보가 반환됩니다.
nft의 경우 erc721과 erc1155로 나뉘어져있습니다.
/app/wallet/balance/page.tsx
, /app/wallet/erc20/page.tsx
, /app/wallet/nft/page.tsx
async function onSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault()
setIsLoading(true)
setError(null) // Clear previous errors when a new request starts
try {
const formData = new FormData(event.currentTarget)
//입력된 지갑 주소로 api에서 지갑 조회
const response = await fetch('/api/wallet/balance?&address=' + body.address , {
method: 'GET',
}).then(response=>response.json()).then(data=>setData(data.data))
} catch (error : any) {
// Capture the error message to display to the user
setError(error.message)
console.error(error)
} finally {
setIsLoading(false)
}
}
입력한 지갑의 코인 잔액에 대하여 반환해줍니다.
/app/api/wallet/balance/route.tsx
, /app/api/wallet/erc20/route.tsx
, /app/api/wallet/erc721/route.tsx
, /app/api/wallet/erc721/route.tsx
export async function GET(request : NextRequest) {
const { searchParams } = new URL(request.url)
const api_token = process.env.NEXT_PUBLIC_BLOCKSDK_TOKEN
const url = process.env.NEXT_PUBLIC_URL as string
const net = process.env.NEXT_PUBLIC_NET
const address = searchParams.get('address')
const res = await fetch(url + net + `/address/`+ address +`/balance?api_token=` + api_token, {
headers: {
'Content-Type': 'application/json',
},
});
const data = await res.json();
return NextResponse.json({ data })
}
생성한 지갑의 privatekey값을 이용하여 소유한 코인을 전송할 수 있습니다.
erc20의 경우 전송할 erc20의 컨트랙트코드가 추가로 입력되어야합니다.
/app/wallet/send/page.tsx
, /app/wallet/send/erc20/page.tsx
async function onSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault()
setIsLoading(true)
setError(null) // Clear previous errors when a new request starts
try {
const formData = new FormData(event.currentTarget)
const response = await fetch('/api/wallet/balance' , {
method: 'POST',
body: JSON.stringify({
from : body.from,
private_key : body.private_key,
to : body.to,
amount : body.amount,
}),
}).then(response=>response.json()).then(data=>setData(data.data))
} catch (error : any) {
// Capture the error message to display to the user
setError(error.message)
console.error(error)
} finally {
setIsLoading(false)
}
}
입력받은 지갑의 암호키와, 받는 사람, 보내는 사람, 보내는 코인 양을 이용하여 암호화폐를 전송합니다.
/app/api/wallet/balance/route.tsx
, /app/api/wallet/erc20/route.tsx
export async function POST(request : NextRequest) {
const { searchParams } = new URL(request.url)
const api_token = process.env.NEXT_PUBLIC_BLOCKSDK_TOKEN
const url = process.env.NEXT_PUBLIC_URL as string
const net = process.env.NEXT_PUBLIC_NET
const payload = await request.json()
const res = await fetch(url + net + `/address/`+ payload.from +`/send?api_token=` + api_token, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
private_key: payload.private_key,
to : payload.to,
amount : payload.amount,
}),
})
const data = await res.json()
return NextResponse.json({data})
}