mirror of git3://git3.w3q/git3-cli
parent
b6e6286b23
commit
c2956f0c41
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"prettier.tabWidth": 4,
|
||||||
|
"vetur.format.options.tabSize": 4
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
import { ethers } from "ethers"
|
||||||
|
import nameServices from "../config/name-services.js"
|
||||||
|
import { ETHStorage } from "../storage/ETHStorage.js"
|
||||||
|
import { SLIStorage } from "../storage/SLIStorage.js"
|
||||||
|
import { getWallet, randomRPC, setupContract } from "./wallet.js"
|
||||||
|
import network from "../config/evm-network.js"
|
||||||
|
import abis from "../config/abis.js"
|
||||||
|
|
||||||
|
export type Git3Protocol = {
|
||||||
|
sender: string
|
||||||
|
senderAddress: string
|
||||||
|
hubAddress: string
|
||||||
|
repoName: string
|
||||||
|
chainId: number
|
||||||
|
netConfig: Record<string, any>
|
||||||
|
wallet: ethers.Wallet
|
||||||
|
contract: ethers.Contract
|
||||||
|
storageClass: any
|
||||||
|
ns?: Record<string, any>
|
||||||
|
nsName?: string
|
||||||
|
nsDomain?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Option = {
|
||||||
|
skipRepoName: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseGit3URI(
|
||||||
|
uri: string,
|
||||||
|
option: Option = { skipRepoName: false }
|
||||||
|
): Git3Protocol {
|
||||||
|
const url = new URL(uri)
|
||||||
|
let sender = url.username || "default"
|
||||||
|
let chainId = url.port ? parseInt(url.port) : null
|
||||||
|
let hub = url.hostname
|
||||||
|
let hubAddress
|
||||||
|
let nsName, nsDomain, ns
|
||||||
|
if (!hub) throw new Error("invalid git3 uri, no hub address")
|
||||||
|
let repoName = url.pathname.slice(1)
|
||||||
|
if (!option.skipRepoName && !repoName)
|
||||||
|
throw new Error("invalid git3 uri, no repo name")
|
||||||
|
|
||||||
|
if (hub.indexOf(".") < 0) {
|
||||||
|
if (url.hostname.startsWith("0x")) {
|
||||||
|
hubAddress = url.hostname
|
||||||
|
} else {
|
||||||
|
throw new Error("invalid git3 uri, hub must be NS or address")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
;[nsName, nsDomain] = url.hostname.split(".")
|
||||||
|
ns = nameServices[nsDomain]
|
||||||
|
if (!ns) throw new Error("invalid name service")
|
||||||
|
chainId = chainId || ns.chainId
|
||||||
|
// Todo: resolve name service
|
||||||
|
// hubAddress = ns.resolver()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!chainId) throw new Error("invalid git3 uri, no chainId")
|
||||||
|
|
||||||
|
let netConfig = network[chainId]
|
||||||
|
if (!netConfig) throw new Error("invalid chainId")
|
||||||
|
|
||||||
|
if (!hubAddress) hubAddress = netConfig.contracts.git3
|
||||||
|
|
||||||
|
let wallet = getWallet(sender)
|
||||||
|
|
||||||
|
let senderAddress = wallet.address
|
||||||
|
|
||||||
|
// route to different storage
|
||||||
|
let storageClass, abi
|
||||||
|
if (chainId == 3334) {
|
||||||
|
storageClass = ETHStorage
|
||||||
|
abi = abis.ETHStorage
|
||||||
|
} else {
|
||||||
|
storageClass = SLIStorage
|
||||||
|
abi = abis.SLIStorage
|
||||||
|
}
|
||||||
|
let rpc = randomRPC(netConfig.rpc)
|
||||||
|
const provider = new ethers.providers.JsonRpcProvider(rpc)
|
||||||
|
|
||||||
|
let contract = setupContract(provider, hubAddress, abi, wallet)
|
||||||
|
wallet = wallet.connect(contract.provider)
|
||||||
|
|
||||||
|
return {
|
||||||
|
sender,
|
||||||
|
senderAddress,
|
||||||
|
hubAddress,
|
||||||
|
repoName,
|
||||||
|
chainId,
|
||||||
|
netConfig,
|
||||||
|
wallet,
|
||||||
|
contract,
|
||||||
|
storageClass,
|
||||||
|
ns,
|
||||||
|
nsName,
|
||||||
|
nsDomain,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
import { mkdirSync, readFileSync } from "fs"
|
||||||
|
import { ethers } from "ethers"
|
||||||
|
|
||||||
|
export function getWallet(wallet: string | null = "default"): ethers.Wallet {
|
||||||
|
if (!wallet) wallet = "default"
|
||||||
|
|
||||||
|
// Todo: 0xaddress find wallet
|
||||||
|
const keyPath = process.env.HOME + "/.git3/keys"
|
||||||
|
mkdirSync(keyPath, { recursive: true })
|
||||||
|
|
||||||
|
const content = readFileSync(`${keyPath}/${wallet}`).toString()
|
||||||
|
const [walletType, key] = content.split("\n")
|
||||||
|
|
||||||
|
let etherWallet =
|
||||||
|
walletType === "privateKey"
|
||||||
|
? new ethers.Wallet(key)
|
||||||
|
: ethers.Wallet.fromMnemonic(key)
|
||||||
|
|
||||||
|
return etherWallet
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setupContract(
|
||||||
|
provider: ethers.providers.JsonRpcProvider,
|
||||||
|
hubAddress: string,
|
||||||
|
abi: string,
|
||||||
|
wallet: ethers.Wallet
|
||||||
|
): ethers.Contract {
|
||||||
|
|
||||||
|
let contract = new ethers.Contract(hubAddress, abi, provider)
|
||||||
|
wallet = wallet.connect(provider)
|
||||||
|
contract = contract.connect(wallet)
|
||||||
|
|
||||||
|
return contract
|
||||||
|
}
|
||||||
|
|
||||||
|
export function randomRPC(rpcs: string[]): string {
|
||||||
|
return rpcs[Math.floor(Math.random() * rpcs.length)]
|
||||||
|
}
|
@ -1,234 +1,278 @@
|
|||||||
import { mkdirSync, readdirSync, readFileSync, writeFileSync, rmSync, existsSync } from 'fs'
|
import { mkdirSync, readdirSync, readFileSync, writeFileSync, rmSync } from "fs"
|
||||||
import { ethers } from 'ethers'
|
import { ethers } from "ethers"
|
||||||
import { Command } from 'commander'
|
import { Command } from "commander"
|
||||||
import bip39 from 'bip39'
|
import bip39 from "bip39"
|
||||||
import inquirer from 'inquirer'
|
import inquirer from "inquirer"
|
||||||
import parse from 'parse-git-config'
|
import { importActions, generateActions } from "./actions.js"
|
||||||
import { importActions, generateActions } from './actions.js'
|
|
||||||
import abis from "../config/abis.js"
|
|
||||||
import network from "../config/evm-network.js"
|
import network from "../config/evm-network.js"
|
||||||
|
import { getWallet, randomRPC } from "../common/wallet.js"
|
||||||
|
import { parseGit3URI } from "../common/git3-protocol.js"
|
||||||
|
import { TxManager } from "../common/tx-manager.js"
|
||||||
const program = new Command()
|
const program = new Command()
|
||||||
|
|
||||||
|
program.name("git3").description("git3 mangement tool").version("0.1.0")
|
||||||
|
|
||||||
program
|
program
|
||||||
.name('git3')
|
.command("generate")
|
||||||
.description('git3 mangement tool')
|
.alias("gen")
|
||||||
.version('0.1.0')
|
.alias("new")
|
||||||
|
.description("generate a cryto wallet to use git3")
|
||||||
program.command('generate')
|
.action(() => {
|
||||||
.alias('gen')
|
inquirer.prompt(generateActions).then((answers) => {
|
||||||
.alias('new')
|
const { keyType, name } = answers
|
||||||
.description('generate a cryto wallet to use git3')
|
const walletType =
|
||||||
.action(() => {
|
keyType === "private key" ? "privateKey" : "mnemonic"
|
||||||
inquirer.prompt(generateActions).then(answers => {
|
|
||||||
const { keyType, name } = answers
|
const keyPath = process.env.HOME + "/.git3/keys"
|
||||||
const walletType = keyType === 'private key' ? 'privateKey' : 'mnemonic'
|
mkdirSync(keyPath, { recursive: true })
|
||||||
|
|
||||||
const keyPath = process.env.HOME + "/.git3/keys"
|
if (readdirSync(keyPath).includes(name)) {
|
||||||
mkdirSync(keyPath, { recursive: true })
|
console.error(`wallet ${name} already exists`)
|
||||||
|
return
|
||||||
if (readdirSync(keyPath).includes(name)) {
|
}
|
||||||
console.error(`wallet ${name} already exists`)
|
|
||||||
return
|
const mnemonic = bip39.generateMnemonic()
|
||||||
}
|
const wallet =
|
||||||
|
keyType === "private key"
|
||||||
const mnemonic = bip39.generateMnemonic()
|
? ethers.Wallet.createRandom()
|
||||||
const wallet = keyType === 'private key'
|
: ethers.Wallet.fromMnemonic(mnemonic)
|
||||||
? ethers.Wallet.createRandom()
|
|
||||||
: ethers.Wallet.fromMnemonic(mnemonic)
|
const content = `${walletType}\n${
|
||||||
|
keyType === "private key" ? wallet.privateKey : mnemonic
|
||||||
const content = `${walletType}\n${keyType === 'private key' ? wallet.privateKey : mnemonic}\n`
|
}\n`
|
||||||
writeFileSync(`${keyPath}/${name}`, content)
|
writeFileSync(`${keyPath}/${name}`, content)
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
program.command('list', { isDefault: true })
|
|
||||||
.alias('ls')
|
|
||||||
.description('list all wallets in user folder ~/.git3/keys')
|
|
||||||
.option('-r, --raw', 'output raw wallet data with pravate key / mnemonic')
|
|
||||||
.action(params => {
|
|
||||||
|
|
||||||
const keyPath = process.env.HOME + "/.git3/keys"
|
|
||||||
mkdirSync(keyPath, { recursive: true })
|
|
||||||
const wallets = readdirSync(keyPath)
|
|
||||||
|
|
||||||
if (wallets.length === 0) {
|
|
||||||
console.log('No wallet found, you can generate one use <git3 new>')
|
|
||||||
}
|
|
||||||
|
|
||||||
wallets.forEach(file => {
|
|
||||||
const content = readFileSync(`${keyPath}/${file}`).toString()
|
|
||||||
|
|
||||||
|
|
||||||
if (params.raw) {
|
|
||||||
console.log(`[${file}]`)
|
|
||||||
console.log(` ${content.split('\n')[0]} - ${content.split('\n')[1]}`)
|
|
||||||
console.log('\t')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`[${file}]`)
|
|
||||||
const [walletType, key] = content.split('\n')
|
|
||||||
const etherWallet = walletType === 'privateKey'
|
|
||||||
? new ethers.Wallet(key)
|
|
||||||
: ethers.Wallet.fromMnemonic(key)
|
|
||||||
const address = etherWallet.address
|
|
||||||
console.log(`address: ${address}`)
|
|
||||||
console.log('\t')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
program.command('import')
|
|
||||||
.description('import a wallet from a private key or mnemonic')
|
|
||||||
.action(() => {
|
|
||||||
inquirer.prompt(importActions).then(answers => {
|
|
||||||
const { keyType, key, name } = answers
|
|
||||||
const walletType = keyType === 'private key' ? 'privateKey' : 'mnemonic'
|
|
||||||
const keyPath = process.env.HOME + "/.git3/keys"
|
|
||||||
mkdirSync(keyPath, { recursive: true })
|
|
||||||
|
|
||||||
if (readdirSync(keyPath).includes(name)) {
|
|
||||||
console.error(`wallet ${name} already exists`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const content = `${walletType}\n${key}\n`
|
|
||||||
writeFileSync(`${keyPath}/${name}`, content)
|
|
||||||
return
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
program.command('delete')
|
|
||||||
.description('delete a wallet')
|
|
||||||
.action(() => {
|
|
||||||
const keyPath = process.env.HOME + "/.git3/keys"
|
|
||||||
mkdirSync(keyPath, { recursive: true })
|
|
||||||
const wallets = readdirSync(keyPath)
|
|
||||||
|
|
||||||
if (wallets.length === 0) {
|
|
||||||
console.error('No wallet found, you can generate one with `git3 generate`')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
inquirer.prompt([
|
|
||||||
{
|
|
||||||
type: 'list',
|
|
||||||
name: 'wallet',
|
|
||||||
message: 'Select wallet to delete',
|
|
||||||
choices: wallets
|
|
||||||
}
|
|
||||||
]).then(answers => {
|
|
||||||
const { wallet } = answers
|
|
||||||
rmSync(`${keyPath}/${wallet}`)
|
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
program.command('create')
|
|
||||||
.argument('[wallet]', 'wallet to use', 'default')
|
|
||||||
.argument('[repo]', 'repo name to create')
|
|
||||||
.description('create a new repo')
|
|
||||||
.action((wallet, repo) => {
|
|
||||||
|
|
||||||
const keyPath = process.env.HOME + "/.git3/keys"
|
|
||||||
mkdirSync(keyPath, { recursive: true })
|
|
||||||
const content = readFileSync(`${keyPath}/${wallet}`).toString()
|
|
||||||
|
|
||||||
const [walletType, key] = content.split('\n')
|
|
||||||
const provider = new ethers.providers.JsonRpcProvider('https://galileo.web3q.io:8545');
|
|
||||||
|
|
||||||
let etherWallet = walletType === 'privateKey'
|
|
||||||
? new ethers.Wallet(key)
|
|
||||||
: ethers.Wallet.fromMnemonic(key)
|
|
||||||
|
|
||||||
etherWallet = etherWallet.connect(provider)
|
|
||||||
let net = network[3334]
|
|
||||||
const contract = new ethers.Contract(
|
|
||||||
net.contracts.git3,
|
|
||||||
abis.ETHStorage,
|
|
||||||
etherWallet)
|
|
||||||
|
|
||||||
|
program
|
||||||
|
.command("list", { isDefault: true })
|
||||||
|
.alias("ls")
|
||||||
|
.description("list all wallets in user folder ~/.git3/keys")
|
||||||
|
.option("-r, --raw", "output raw wallet data with pravate key / mnemonic")
|
||||||
|
.action((params) => {
|
||||||
|
const keyPath = process.env.HOME + "/.git3/keys"
|
||||||
|
mkdirSync(keyPath, { recursive: true })
|
||||||
|
const wallets = readdirSync(keyPath)
|
||||||
|
|
||||||
|
if (wallets.length === 0) {
|
||||||
|
console.log("No wallet found, you can generate one use <git3 new>")
|
||||||
|
}
|
||||||
|
|
||||||
contract.repoNameToOwner(Buffer.from(repo))
|
wallets.forEach((file) => {
|
||||||
.then((res: any) => { console.log(res) })
|
const content = readFileSync(`${keyPath}/${file}`).toString()
|
||||||
.catch((err: any) => { console.error(err) })
|
|
||||||
contract.createRepo(Buffer.from(repo))
|
if (params.raw) {
|
||||||
.then((res: any) => { console.log(res) })
|
console.log(`[${file}]`)
|
||||||
.catch((err: any) => { console.error(err) })
|
console.log(
|
||||||
|
` ${content.split("\n")[0]} - ${content.split("\n")[1]}`
|
||||||
|
)
|
||||||
|
console.log("\t")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[${file}]`)
|
||||||
|
const [walletType, key] = content.split("\n")
|
||||||
|
const etherWallet =
|
||||||
|
walletType === "privateKey"
|
||||||
|
? new ethers.Wallet(key)
|
||||||
|
: ethers.Wallet.fromMnemonic(key)
|
||||||
|
const address = etherWallet.address
|
||||||
|
console.log(`address: ${address}`)
|
||||||
|
console.log("\t")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
})
|
program
|
||||||
|
.command("import")
|
||||||
|
.description("import a wallet from a private key or mnemonic")
|
||||||
|
.action(() => {
|
||||||
|
inquirer.prompt(importActions).then((answers) => {
|
||||||
|
const { keyType, key, name } = answers
|
||||||
|
const walletType =
|
||||||
|
keyType === "private key" ? "privateKey" : "mnemonic"
|
||||||
|
const keyPath = process.env.HOME + "/.git3/keys"
|
||||||
|
mkdirSync(keyPath, { recursive: true })
|
||||||
|
|
||||||
|
if (readdirSync(keyPath).includes(name)) {
|
||||||
|
console.error(`wallet ${name} already exists`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = `${walletType}\n${key}\n`
|
||||||
|
writeFileSync(`${keyPath}/${name}`, content)
|
||||||
|
return
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
program.command('info')
|
program
|
||||||
.argument('[wallet]', 'wallet you want to get info', 'default')
|
.command("delete")
|
||||||
.description('get info of a wallet')
|
.description("delete a wallet")
|
||||||
.action(wallet => {
|
.action(() => {
|
||||||
|
const keyPath = process.env.HOME + "/.git3/keys"
|
||||||
|
mkdirSync(keyPath, { recursive: true })
|
||||||
|
const wallets = readdirSync(keyPath)
|
||||||
|
|
||||||
|
if (wallets.length === 0) {
|
||||||
|
console.error(
|
||||||
|
"No wallet found, you can generate one with `git3 generate`"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const keyPath = process.env.HOME + "/.git3/keys"
|
inquirer
|
||||||
mkdirSync(keyPath, { recursive: true })
|
.prompt([
|
||||||
|
{
|
||||||
|
type: "list",
|
||||||
|
name: "wallet",
|
||||||
|
message: "Select wallet to delete",
|
||||||
|
choices: wallets,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.then((answers) => {
|
||||||
|
const { wallet } = answers
|
||||||
|
rmSync(`${keyPath}/${wallet}`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
const content = readFileSync(`${keyPath}/${wallet}`).toString()
|
program
|
||||||
const [walletType, key] = content.split('\n')
|
.command("create")
|
||||||
const provider = new ethers.providers.JsonRpcProvider('https://galileo.web3q.io:8545');
|
.argument("<uri>", "ex: default@git3.w3q/repo_name")
|
||||||
|
.description("create a new repo")
|
||||||
|
.action(async (uri) => {
|
||||||
|
if (!uri.startsWith("git3://")) {
|
||||||
|
uri = "git3://" + uri
|
||||||
|
}
|
||||||
|
const protocol = parseGit3URI(uri)
|
||||||
|
let owner = await protocol.contract.repoNameToOwner(
|
||||||
|
Buffer.from(protocol.repoName)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (owner != "0x0000000000000000000000000000000000000000") {
|
||||||
|
console.error(`repo ${protocol.repoName} already exists`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.log(
|
||||||
|
`creating repo ${protocol.repoName} on ${protocol.netConfig.name}...`
|
||||||
|
)
|
||||||
|
const txManager = new TxManager(
|
||||||
|
protocol.contract,
|
||||||
|
protocol.chainId,
|
||||||
|
protocol.netConfig.txConst
|
||||||
|
)
|
||||||
|
let receipt = await txManager.SendCall("createRepo", [
|
||||||
|
Buffer.from(protocol.repoName),
|
||||||
|
])
|
||||||
|
if (
|
||||||
|
protocol.netConfig.explorers &&
|
||||||
|
protocol.netConfig.explorers.length > 0
|
||||||
|
) {
|
||||||
|
console.log(
|
||||||
|
protocol.netConfig.explorers[0].url.replace(/\/+$/, "") +
|
||||||
|
"/tx/" +
|
||||||
|
receipt.transactionHash
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
console.log(receipt.transactionHash)
|
||||||
|
}
|
||||||
|
console.log(`repo ${protocol.repoName} created.`)
|
||||||
|
})
|
||||||
|
|
||||||
let etherWallet = walletType === 'privateKey'
|
program
|
||||||
? new ethers.Wallet(key)
|
.command("info")
|
||||||
: ethers.Wallet.fromMnemonic(key)
|
.argument("[wallet]", "wallet you want to get info", "default")
|
||||||
|
.description("get info of a wallet")
|
||||||
|
.action((wallet) => {
|
||||||
|
let etherWallet = getWallet(wallet)
|
||||||
|
|
||||||
etherWallet = etherWallet.connect(provider)
|
const address = etherWallet.address
|
||||||
const address = etherWallet.address
|
|
||||||
|
|
||||||
etherWallet.getBalance()
|
|
||||||
.then(balance => {
|
|
||||||
console.log(`wallet: ${wallet}`)
|
console.log(`wallet: ${wallet}`)
|
||||||
console.log(`address: ${address}`)
|
console.log(`address: ${address}`)
|
||||||
console.log(`balance: ${ethers.utils.formatUnits(balance)} eth`)
|
|
||||||
})
|
for (let [_, net] of Object.entries(network)) {
|
||||||
.catch(err => {
|
const provider = new ethers.providers.JsonRpcProvider(
|
||||||
console.error(err)
|
randomRPC(net.rpc)
|
||||||
return
|
)
|
||||||
})
|
const balance = provider.getBalance(address)
|
||||||
})
|
balance.then((res) => {
|
||||||
|
console.log(
|
||||||
program.command('set-wallet')
|
`[${net.name}] balance: ${ethers.utils.formatUnits(
|
||||||
.alias('set')
|
res,
|
||||||
.argument('<git3>', 'git3 remote')
|
net.nativeCurrency.decimals
|
||||||
.argument('[wallet]', 'wallet you want to bind', 'default')
|
)} ${net.nativeCurrency.symbol}`
|
||||||
.description('bind git3 remotes with a wallet')
|
)
|
||||||
.action((git3, wallet) => {
|
})
|
||||||
const currentConfig = parse.sync()
|
|
||||||
|
|
||||||
const existingRemote = currentConfig[`remote "${git3}"`]
|
|
||||||
const keyPath = process.env.HOME + "/.git3/keys"
|
|
||||||
mkdirSync(keyPath, { recursive: true })
|
|
||||||
|
|
||||||
if (!existsSync(`${keyPath}/${wallet}`)) {
|
|
||||||
console.error(`wallet ${wallet} not found, use <git3 new> to generate one`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (existingRemote) {
|
|
||||||
const newConfig = {
|
|
||||||
...currentConfig,
|
|
||||||
[`remote "${git3}"`]: {
|
|
||||||
...existingRemote,
|
|
||||||
wallet
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
// console.log(newConfig)
|
program
|
||||||
// const writer = createWriteStream('config', 'w')
|
.command("clear")
|
||||||
let newConfigText = ''
|
.description("clear pending nonce")
|
||||||
Object.keys(newConfig).forEach(key => {
|
.argument("<uri>", "ex: default@git3.w3q")
|
||||||
newConfigText += `[${key}]\n`
|
.argument("[num]", "number of pending nonce to clear", 1)
|
||||||
Object.keys(newConfig[key]).forEach(subKey => {
|
.action(async (uri,num) => {
|
||||||
newConfigText += `\t${subKey} = ${newConfig[key][subKey]}\n`
|
if (!uri.startsWith("git3://")) {
|
||||||
})
|
uri = "git3://" + uri
|
||||||
})
|
}
|
||||||
let path = parse.resolveConfigPath("global") || ""
|
const protocol = parseGit3URI(uri, { skipRepoName: true })
|
||||||
writeFileSync(path, newConfigText)
|
const txManager = new TxManager(
|
||||||
} else {
|
protocol.contract,
|
||||||
console.error(`remote ${git3} not found`)
|
protocol.chainId,
|
||||||
console.error('you can add a remote with `git remote add <name> <url>')
|
protocol.netConfig.txConst
|
||||||
}
|
)
|
||||||
})
|
let nonce = await protocol.wallet.getTransactionCount()
|
||||||
|
console.log(`current nonce: ${nonce}`)
|
||||||
|
await txManager.clearPendingNonce(num)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Todo: set-wallet temporarily useless
|
||||||
|
// program
|
||||||
|
// .command("set-wallet")
|
||||||
|
// .alias("set")
|
||||||
|
// .argument("<git3>", "git3 remote")
|
||||||
|
// .argument("[wallet]", "wallet you want to bind", "default")
|
||||||
|
// .description("bind git3 remotes with a wallet")
|
||||||
|
// .action((git3, wallet) => {
|
||||||
|
// const currentConfig = parse.sync()
|
||||||
|
|
||||||
|
// const existingRemote = currentConfig[`remote "${git3}"`]
|
||||||
|
// const keyPath = process.env.HOME + "/.git3/keys"
|
||||||
|
// mkdirSync(keyPath, { recursive: true })
|
||||||
|
|
||||||
|
// if (!existsSync(`${keyPath}/${wallet}`)) {
|
||||||
|
// console.error(
|
||||||
|
// `wallet ${wallet} not found, use <git3 new> to generate one`
|
||||||
|
// )
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (existingRemote) {
|
||||||
|
// const newConfig = {
|
||||||
|
// ...currentConfig,
|
||||||
|
// [`remote "${git3}"`]: {
|
||||||
|
// ...existingRemote,
|
||||||
|
// wallet,
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // console.log(newConfig)
|
||||||
|
// // const writer = createWriteStream('config', 'w')
|
||||||
|
// let newConfigText = ""
|
||||||
|
// Object.keys(newConfig).forEach((key) => {
|
||||||
|
// newConfigText += `[${key}]\n`
|
||||||
|
// Object.keys(newConfig[key]).forEach((subKey) => {
|
||||||
|
// newConfigText += `\t${subKey} = ${newConfig[key][subKey]}\n`
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// let path = parse.resolveConfigPath("global") || ""
|
||||||
|
// writeFileSync(path, newConfigText)
|
||||||
|
// } else {
|
||||||
|
// console.error(`remote ${git3} not found`)
|
||||||
|
// console.error(
|
||||||
|
// "you can add a remote with `git remote add <name> <url>"
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
|
||||||
program.parse()
|
program.parse()
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
import { mkdirSync, readFileSync } from "fs"
|
|
||||||
import { ethers } from 'ethers'
|
|
||||||
|
|
||||||
export function getWallet(sender: string | null): ethers.Wallet {
|
|
||||||
// Todo: according sender address to select wallet, if sender==null then use default wallet
|
|
||||||
const wallet = 'default'
|
|
||||||
|
|
||||||
const keyPath = process.env.HOME + "/.git3/keys"
|
|
||||||
mkdirSync(keyPath, { recursive: true })
|
|
||||||
|
|
||||||
const content = readFileSync(`${keyPath}/${wallet}`).toString()
|
|
||||||
const [walletType, key] = content.split('\n')
|
|
||||||
|
|
||||||
let etherWallet = walletType === 'privateKey'
|
|
||||||
? new ethers.Wallet(key)
|
|
||||||
: ethers.Wallet.fromMnemonic(key)
|
|
||||||
|
|
||||||
return etherWallet
|
|
||||||
}
|
|
Loading…
Reference in new issue