wallet 만들기
변수 & 상수
type wallet struct {
	
	privateKey *ecdsa.PrivateKey
	
	Address string
}
var w *wallet
const (
	fileName string = "fdongfdong.wallet"
)
함수
Wallet() : 함수 호출 시 사용자가 wallet이 없다면 키페어를 만들어 파일 형태로 저장해준다.
func Wallet() *wallet {
	if w == nil {
		w = &wallet{}
		
		if hasWalletFile() {
			w.privateKey = restoreKey()
			
		} else {
			
			
			key := createPrivKey()
			
			persistKey(key)
			
			w.privateKey = key
		}
		w.Address = aFromK(w.privateKey)
	}
	return w
}
hasWalletFile() : 해당하는 파일의 이름을 가진 파일이 존재하는지 알려준다.
func hasWalletFile() bool {
	_, err := os.Stat(fileName)
	return !os.IsNotExist(err)
}
resotoreKey() : 키 파일을 읽어 해당 키를 반한한다.
func restoreKey() (key *ecdsa.PrivateKey) {
	keyAsByte, err := os.ReadFile(fileName)
	utils.HandleErr(err)
	
	key, err = x509.ParseECPrivateKey(keyAsByte)
	utils.HandleErr(err)
	return
}
createPrivKey() : Key Pair를 생성해준다.
func createPrivKey() *ecdsa.PrivateKey {
	
	privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	utils.HandleErr(err)
	return privKey
}
persistKey() : key를 받아 byte 타입의 파일로 저장한다.
func persistKey(key *ecdsa.PrivateKey) {
	
	bytes, err := x509.MarshalECPrivateKey(key)
	utils.HandleErr(err)
	
	err = os.WriteFile(fileName, bytes, 0644)
	utils.HandleErr(err)
}
func aFromK(key *ecdsa.PrivateKey) string {
	return encodeBigInts(key.X.Bytes(), key.Y.Bytes())
}
encodeBigInts() : public key의, a,b 값을 합쳐 16진수 문자열형태로 반환한다.
func encodeBigInts(a, b []byte) string {
	
	z := append(a, b...)
	return fmt.Sprintf("%x", z)
}