go install github.com/swaggo/swag/cmd/swag
~/go/bin/swag
실행파일이 설치된다.
swag init
docs/docs.go
가 생성된다.
swag fmt
go install github.com/swaggo/swag/cmd/swag
~/go/bin/swag
실행파일이 설치된다.
swag init
docs/docs.go
가 생성된다.
swag fmt
Ethereum의 경우 버전에 따라 트랜잭션에 gasPrice를 쓸 지, maxFeePerGas/maxPriorityFeePerGas 를 쓸 지가 정해진다. https://ethereum.stackexchange.com/questions/147692/how-to-get-public-key-by-the-transaction-hash 를 참고.
주소를 얻을 때, Public key에서 앞의 한 바이트(0x04)를 빼고, keccak256을 돌리는 부분에 유의하자.
const { ethers } = require("hardhat");
// 트랜잭션 서명 값
// const r = "0xe680637b83a1dd102364503bd77979b87c92ba651132a4df8e839af69c20af95";
// const s = "0x65becfa32384747adb05f543397baaf23d1c55fa28d0c9a38924912dae6df28f";
// const v = 12266684226873;
// const chainId = 6133342113419;
// 트랜잭션 해시
const txHash = "0xc7159866fb5b94d291e8624bdc731b7a6d46533b398065de7aa7dd1af7b6aa36";
const ethermainHash = "0xef120deb6ff2e516ad44724d220c0cd73166d169a2a0b0f66dfb5613d2d6169c"
const sepoliaHash = "0xfe4ddad4cae9ea353fc91441ee5db6c70bd5468673d907926be92dd4b8a63f63"
// 실제 트랜잭션에 사용된 private key. 아무거나 넣자.
const privateKey = "0x0000000000000000000000000000000000000000000000000000000000000001";
// Web3 프로바이더 설정 (Hardhat 로컬 노드 사용 예시)
const provider = ethers.provider;
// 서명된 트랜잭션 정보 가져오기
async function getPublicKeyFromTransactionHash(provider, txHash) {
// Fetch the transaction using the transaction hash and provier
const tx = await provider.getTransaction(txHash);
console.log(tx);
// Extract the all the relevant fields from the transaction (We need all of them)
const unsignedTx = {
gasPrice: tx.gasPrice,
gasLimit: tx.gasLimit,
value: tx.value,
nonce: tx.nonce,
data: tx.data,
chainId: tx.chainId,
to: tx.to,
type: tx.type,
// maxFeePerGas: tx.maxFeePerGas,
// maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
};
// Serializing tx without the signature
const serializedTx = ethers.utils.serializeTransaction(unsignedTx);
// Extract the signature (v, r, s) from the transaction
const { v, r, s } = tx;
// Join splitted signature
const signature = ethers.utils.joinSignature({ v, r, s });
const recoveredPublicKey = ethers.utils.recoverPublicKey(
ethers.utils.keccak256(serializedTx),
signature,
);
console.log("recoveredPublicKey:", recoveredPublicKey);
const keccak = ethers.utils.keccak256("0x" + recoveredPublicKey.slice(4))
console.log("keccak256 of recoveredPublicKey:", keccak, ethers.utils.keccak256("0x" + recoveredPublicKey.slice(4)));
// Recover the address or public key with (replace recoverAddress by recoverPublicKey) associated with the transaction
return ethers.utils.recoverAddress(
ethers.utils.keccak256(serializedTx),
signature
);
}
async function main() {
const address = await getPublicKeyFromTransactionHash(provider, txHash);
console.log("Address:", address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
apt-get install -y fonts-nanum
fc-cache -fv
rm ~/.cache/matplotlib -rf
혹은 Windows에서는
from matplotlib import font_manager, rc
font_path = 'C:/Windows/Fonts/NGULIM.TTF'
font = font_manager.FontProperties(fname=font_path).get_name()
rc('font', family=font)
sudo apt-get install fail2ban
sudo systemctl enable fail2ban.service
/etc/fail2ban/
아래에 설정 파일이 있다. jail.d/
아래 파일을 추가/수정.
import { subtask } from "hardhat/config";
import { LedgerSigner } from "@ethers-ext/signer-ledger";
import HIDTransport from "@ledgerhq/hw-transport-node-hid";
const USE_LEDGER = {
"61331819613419": true,
"2022": true
};
subtask("getLedgerSigner", "Get LedgerSigner")
.addOptionalPositionalParam("accountNumber", "Account number of the Ledger", "0")
.setAction(async (taskArgs) => {
const accountNumber = taskArgs.accountNumber;
const chainId = (await ethers.provider.getNetwork()).chainId;
const ledgerNeeded = USE_LEDGER[chainId] ?? false;
console.log("ChainID:", chainId, "LedgerNeeded:", ledgerNeeded);
if (ledgerNeeded) {
const _master = new LedgerSigner(HIDTransport, ethers.provider, `m/44'/60'/${accountNumber}'/0/0`);
_master.getFeeData = async () => {
return {
gasPrice: ethers.BigNumber.from(0),
lastBaseFeePerGas: ethers.BigNumber.from(0),
maxFeePerGas: ethers.utils.parseUnits("800", "gwei"),
maxPriorityFeePerGas: ethers.utils.parseUnits("800", "gwei"),
};
};
console.log(`LedgerSinger: m/44'/60'/${accountNumber}'/0/0:`, await _master.getAddress());
_master.getBalance = async function() {
return await this.provider.getBalance(this.getAddress());
};
return _master;
}
const accounts = await ethers.getSigners();
return accounts[accountNumber];
});
사용할 때는 hre를 이용해서 다음과 같이 하면 된다.
import { task } from "hardhat/config";
import './subtasks/getLedgerSigner';
task("ledgerBalance", "Prints an account's balance")
.addOptionalPositionalParam("accountNumber", "The account number of the ledger", "0")
.setAction(async (taskArgs) => {
const signer = await hre.run("getLedgerSigner", { accountNumber: taskArgs.accountNumber });
console.log("Signer Address:", await signer.getAddress());
const balance = await signer.getBalance();
console.log(ethers.utils.formatEther(balance), "ETH");
});
vue.js로 작성한 코드를 yarn serve
로 dev server를 돌릴 때 호스트 네임을 주는 경우 “Invalid Host header”를 낸다.
다음을 vue.config.js
의 devServer
에 allowedHosts: "all"
을 추가하면 된다.
devServer: {
port: 8888, // 변경하려는 포트 번호로 대체
allowedHosts: "all",
}
import { ethers } from 'ethers';
import contract_ABI from './abi/contract_ABI.json';
const provider = new ethers.JsonRpcProvider("http://mainnet.dasomoli.org:8545");
const contract_address = "0x1234567890123456789012345678901234567890";
const contract = new ethers.Contract(contract_address, contract_ABI, provider);
const balanceOf = contract.balanceOf(account_address, { blockTag: 12345678 });
위처럼 호출 시 blockTag:
와 함께 blockNumber를 주면 된다.
ethers.js v5 기준
const contract = await ethers.getContractAt("DasomOLIContract", contract_address);
// DasomEvent(type arg1, ...)
const filter = contract.filters.DasomEvent();
const currentBlock = await ethers.provider.getBlockNumber();
const fromBlock = currentBlock - 86400;
const events = await ethers.provider.getLogs({
...filter,
fromBlock: fromBlock,
toBlock: currentBlock,
});
if (events.length > 0) {
events.forEach((event: Log) => {
console.log(`Dasom event found in block ${event.blockNumber}:`);
console.log(`Transaction Hash: ${event.transactionHash}`);
console.log(`Transaction data: ${event.data}`);
const parsedLog = contract.interface.parseLog(event);
const args = parsedLog.args;
const arg1 = args.arg1;
console.log(`Log Data:`, parsedLog.args);
console.log('--------------------------');
});
}
맥에서 설치는 다음과 같다. 우분투는 아마도 apt-get install 을 사용할 것이다.
$ brew install jq
사용법은 값을 얻고 싶은 필드 키를 주면 된다. 뒤에 입력 파일 이름을 주지 않으면 stdin을 입력으로 받는다.
jq “.key” [intput filename]
따라서 curl 이나 echo, cat 등으로 출력을 파이프로 넘겨서 stdin 입력으로 jq에 넘겨서 원하는 데이터를 얻으면 된다. 예를 들어 다음과 같은 데이터를 curl을 통해 얻었다고 하자.
$ curl -X POST "https://login.dasomoli.org/login/2fa" -H "accept: application/json;charset=UTF-8" -H "X-AUTH-MOBILE: true" -H "Content-Type: application/json;charset=UTF-8" -d "{ \"otpCode\": \"123456\", \"password\": \"PASSWORD\", \"userId\": \"dasomoli\"}"
{
"resultCode": "success",
"resultMessage": "Successful",
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJqdXN0aW55IiwiaW5mbyI6eyJ1c2VySWQiOiJqdXN0aW55IiwibmFtZSI6Ikp1c3RpbiIsImFjY291bnQiOiIweEY2NTUwZTk4ZTVDZUFiRjVkRmQ4NTcxYzY3MGI1Zjg0M0U4OTMzNzAiLCJzeW1ib2wiOiJLU1RBX0RFViIsImVtYWlsIjoianVzdGluLnlhbmdAY3J5cHRlZC5jby5rciIsImxvZ2luVGltZSI6MH0sInJvbGVzIjoiUk9MRV9VU0VSIiwiaWF0IjoxNjk3NDQxMTY3LCJleHAiOjE2OTc0NDQ3Njd9.XVT7RIKybB0hgYzcJvZx9voGlolza83RrxuCsK0i-vo",
"refreshToken": "eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2OTc0NDExNjcsImV4cCI6MTY5ODA0NTk2N30.auHUC75qf-Xz--e8JAKvtosaYnUB_Hx5-RKTUZyC-ZM"
}
}
여기서 data 안에 있는 accessToken 값을 얻고 싶다면, 다음과 같이 하면 된다.
$ curl -X POST "https://login.dasomoli.org/login/2fa" -H "accept: application/json;charset=UTF-8" -H "X-AUTH-MOBILE: true" -H "Content-Type: application/json;charset=UTF-8" -d "{ \"otpCode\": \"123456\", \"password\": \"PASSWORD\", \"userId\": \"dasomoli\"}" | jq ".data.accessToken"
쉘 스크립트 내에서 위의 값을 ACCESS_TOKEN 이라는 변수에 넣었을 때, 앞 뒤로 붙는 ” 문자를 없애고 싶다면 다음과 같이 한다.
ACCESS_TOKEN="${ACCESS_TOKEN//\"/}"
assert
with an argument that evaluates to false.unchecked { ... }
block.5 / 0
or 23 % 0
)..pop()
on an empty array.bytesN
or an array slice at an out-of-bounds or negative index (i.e. x[i]
where i >= x.length
or i < 0
).