728x90
넌작스 다운로드 해주기.
wallet/server.ts
import express from 'express'
import nunjucks from 'nunjucks'
import { Wallet } from './wallet'
import axios from 'axios'
const app = express()
const userid = process.env.USERID || 'podo'
const userpw = process.env.USERPW || '1234'
const baseurl = process.env.BASEURL || 'http://localhost:3000'
const baseAuth = Buffer.from(userid + ':' + userpw).toString('base64')
const request = axios.create({
baseURL: 'http://localhost:3000',
headers: {
Authorization: 'Basic' + baseAuth,
'Content-type': 'application/json',
},
})
app.use(express.json())
app.set('view engine', 'html')
nunjucks.configure('views', {
express: app,
watch: true,
})
app.get('/', (req, res) => {
res.render('index')
})
app.post('/newWallet', (req, res) => {
res.json(new Wallet())
})
app.post('/walletList', (req, res) => {
console.log('wallet List')
const list = Wallet.getWalletList()
res.json(list)
})
app.get('/wallet/:account', (req, res) => {
const { account } = req.params
const privateKey = Wallet.getWalletPrivateKey(account)
res.json(new Wallet(privateKey))
})
app.post('/sendTransaction', async (req, res) => {
console.log(req.body)
const {
sender: { account, publicKey },
received,
amount,
} = req.body
const signature = Wallet.createSign(req.body)
//서명 받을 때 필요한 값 sha256( 보낼사람: 공개키 + 받는사람:계정, 보낼금액).toString
//hash + privateKEy => 서명
const txObject = {
sender: publicKey,
received,
amount,
signature,
}
console.log(txObject)
const response = await request.post('/sendTransaction', txObject)
console.log(response.data)
res.json({})
})
app.listen(3005, () => {
console.log('서버 시작', 3005)
})
//sendtransaction
+ 루트디렉토리에 data라는 폴더 만들기.
여기에 지갑명을 저장할것임.
wallet/wallet.ts
import { randomBytes } from 'crypto'
import elliptic from 'elliptic'
import fs from 'fs'
import path from 'path'
import { SHA256 } from 'crypto-js'
const dir = path.join(__dirname, '../data')
const ec = new elliptic.ec('secp256k1')
export class Wallet {
public privateKey: string
public publicKey: string
public account: string
public balance: number
constructor(_privateKey: string = '') {
this.privateKey = this.getPrivateKey()
this.publicKey = this.getPublicKey()
this.account = this.getAccount()
this.balance = 0
Wallet.createWallet(this)
}
static createWallet(myWallet: Wallet) {
const filename = path.join(dir, myWallet.account)
const filecontent = myWallet.privateKey
//파일명을 account
// 내용을 privatekey
fs.writeFileSync(filename, filecontent)
}
static getWalletList(): string[] {
const files: string[] = fs.readdirSync(dir)
return files
}
static getWalletPrivateKey(_account: string) {
const filepath = path.join(dir, _account)
const filecontent = fs.readFileSync(filepath)
return filecontent.toString()
}
static createSign(_obj: any): elliptic.ec.Signature {
const {
sender: { account, publicKey },
received,
amount,
} = _obj
const hash: string = SHA256([publicKey, received, amount].join('')).toString()
const privateKey: string = Wallet.getWalletPrivateKey(account)
const keyPair: elliptic.ec.KeyPair = ec.keyFromPrivate(privateKey)
return keyPair.sign(hash, 'hex')
}
public getPrivateKey(): string {
return randomBytes(32).toString('hex')
}
public getPublicKey(): string {
//개인키 -> 공개키
//개인키 :string임.
const keyPair = ec.keyFromPrivate(this.privateKey)
return keyPair.getPublic().encode('hex', true)
}
public getAccount(): string {
return Buffer.from(this.publicKey).slice(26).toString()
}
}
wallet/transaction.ts
// 비트코인
interface ITxIn {
txOutId: String
txOutIndex: number
signature?: any
}
interface ITxOut {
address: string
amount: number
}
interface ITransaction {
hash: string
txtins: ITxIn[]
txouts: ITxOut[]
}
src/core/wallet/wallet.ts
import elliptic from 'elliptic'
import { StringifyOptions } from 'querystring'
import { SHA256 } from 'crypto-js'
const ec = new elliptic.ec('secp256k1')
export type Signature = elliptic.ec.Signature
export interface ReceivedTx {
sender: string
received: string
amount: number
signature: Signature
}
export class Wallet {
public publicKey: string
public account: String
public balance: number
public signature: Signature
constructor(_sender: string, _stinature: Signature) {
this.publicKey = _sender
this.account = this.getAccount()
this.balance = 0
this.signature = _stinature
}
static sendTransaction(_receivedTx: ReceivedTx) {
//ToDo :서명검증
// 공개키, 보내는 사람:공개키, 받는사람:계정, 보낼금액
//todo : 보내는 사람의 지갑정보 최신화 //publickey
const verify = Wallet.getVerify(_receivedTx)
if (verify.isError) throw new Error(verify.error)
const myWallet = new this(_receivedTx.sender, _receivedTx.signature)
//todo : balance 확인
// todo: 트랜잭션 만드는 과정
console.log(verify.isError)
}
static getVerify(_receivedTx: ReceivedTx): Failable<undefined, string> {
const { sender, received, amount, signature } = _receivedTx
const data: any[] = [sender, received, amount]
const hash: string = SHA256(data.join('')).toString()
//todo: 타원곡선알고리즘 사용
const keyPair = ec.keyFromPublic(sender, 'hex')
const isVerify = keyPair.verify(hash, signature)
if (!isVerify) return { isError: true, error: '서명이 잘못되었습니다.' }
return { isError: false, value: undefined }
}
getAccount(): string {
return Buffer.from(this.publicKey).slice(26).toString()
}
}
views/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<h1>Hello Wallet</h1>
<button id="wallet_btn">지갑생성</button>
<ul id="wallet_list">
<li>CoinName: gyuCoin</li>
<li>
account:
<span class="account"></span>
</li>
<li>
private Key:
<span class="privateKey"></span>
</li>
<li>
public key:
<span class="publicKey"></span>
</li>
<li>
balance:
<span class="balance"></span>
</li>
</ul>
<h1>지갑목록</h1>
<button id="wallet_list_btn">지갑목록 버튼</button>
<div class="wallet_list2">
<ul>
목록 버튼을 누르세요.
</ul>
<h3>Transaction</h3>
<form id="transaction_frm">
<ul>
<li>받는 사람: <input id="received" placeholder="보낼 계정" /></li>
<li>amount: <input id="amount" placeholder="보낼 금액" /></li>
</ul>
<input type="submit" value="전송" />
</form>
</div>
<script type="text/javascript">
const walletBtn = document.querySelector('#wallet_btn')
const transaction_frm = document.querySelector('#transaction_frm')
const WalletListBtn = document.querySelector('#wallet_list_btn')
const createWallet = async () => {
const response = await axios.post('/newWallet', null)
console.log(response.data)
}
const submitHandler = async (e) => {
e.preventDefault()
const publicKey = document.querySelector('.publicKey').innerHTML
const account = document.querySelector('.account').innerHTML
const data = {
sender: {
publicKey,
account,
},
received: e.target.received.value,
amount: parseInt(e.target.amount.value),
}
const response = await axios.post('/sendTransaction', data)
}
const view = (wallet) => {
const account = document.querySelector('.account')
const publicKey = document.querySelector('.publicKey')
const privateKey = document.querySelector('.privateKey')
const balance = document.querySelector('.balance')
account.innerHTML = wallet.account
publicKey.innerHTML = wallet.publicKey
privateKey.innerHTML = wallet.privateKey
balance.innerHTML = wallet.balance
}
const getView = async (account) => {
const response = await axios.get(`/wallet/${account}`)
console.log(response.data)
view(response.data)
}
const getWalletList = async () => {
const walletList = document.querySelector('.wallet_list2 > ul')
const response = await axios.post('/walletList', null)
const list = response.data.map((account) => {
return `<li onClick="getView('${account}')">${account}</li>`
})
walletList.innerHTML = list
}
walletBtn.addEventListener('click', createWallet)
WalletListBtn.addEventListener('click', getWalletList)
transaction_frm.addEventListener('submit', submitHandler)
</script>
</body>
</html>
server.ts와 index.ts 서버 모두 실행해주어야함!!
지갑 생성 버튼 누르면, data 디렉토리에 지갑주소 하나 추가됨!
지갑목록 버튼을 누르면 여태 생성한 지갑주소 목록이 모두 나온다.
여기서 개별 지갑주소를 누르면?
지갑생성 아래에 클릭한 정보가 입력되고,
트랜잭션에서, 선택한 지갑주소를 제외하고 아무거나 선택해서 코인을 보낼 수 있다.
근데 나는 이상하게, 계좌를 선택해도 다른 계좌(처음보는)가... 입력된다.. 뭐지.
728x90
'블록체인' 카테고리의 다른 글
[이더리움] test account 만들어 메타마스크 사용해보기 (0) | 2022.06.27 |
---|---|
[이더리움] 리눅스 환경에 Go lang(Go 언어), Geth 설치하기 (0) | 2022.06.27 |
[Typescript] 암호화폐 지갑 대~충 구현해보기(찍먹) (0) | 2022.06.16 |
암호화폐 지갑(wallet)이란? (0) | 2022.06.16 |
[Typescript, 블록체인] P2P 네트워크를 통한 브로드캐스팅 구현하기 (0) | 2022.06.15 |