Skip to content

Commit

Permalink
Added initial renew support to ENS CLI.
Browse files Browse the repository at this point in the history
  • Loading branch information
ricmoo committed May 1, 2020
1 parent 28800d7 commit 54dfb75
Showing 1 changed file with 136 additions and 1 deletion.
137 changes: 136 additions & 1 deletion packages/cli/src.ts/bin/ethers-ens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ const ethControllerAbi = [
const ethRegistrarAbi = [
"function ownerOf(uint256 tokenId) view returns (address)",
"function reclaim(uint256 id, address owner) @500000",
"function safeTransferFrom(address from, address to, uint256 tokenId) @500000"
"function safeTransferFrom(address from, address to, uint256 tokenId) @500000",
"function nameExpires(uint256 id) external view returns(uint)"
];

const resolverAbi = [
Expand Down Expand Up @@ -867,6 +868,140 @@ class ReclaimPlugin extends AddressAccountPlugin {
}
cli.addPlugin("reclaim", ReclaimPlugin);

function zpad(value: number, length: number): string {
let v = String(value);
while (v.length < length) { v = "0" + v; }
return v;
}

function formatDate(date: Date): string {
const count = Math.round((date.getTime() - (new Date()).getTime()) / (24 * 60 * 60 * 1000))
return [
date.getFullYear(),
zpad(date.getMonth() + 1, 2),
zpad(date.getDate(), 2)
].join("-") + ` (${ count } days from now)`;
}

class RenewPlugin extends EnsPlugin {
labels: ReadonlyArray<string>;

// Only one of these two will be set
duration: number;
until: string;

static getHelp(): Help {
return {
name: "renew NAME [ NAME ... ]",
help: "Reset the controller by the registrant"
}
}

static getOptionHelp(): Array<Help> {
return [
{
name: "[ --duration DAYS ]",
help: "Register duration (default: 365 days)"
},
{
name: "[ --until YYYY-MM-DD ]",
help: "Register until date"
},
];
}

getDuration(startDate: number, until: string): number {
const match = until.match(/^(\d\d\d\d)-(\d\d)-(\d\d)$/);
if (!match) {
this.throwError("invalid date format; use YYYY-MM-DD");
}
const year = parseInt(match[1]);
const month = parseInt(match[2]);
const day = parseInt(match[3]);
// Not perfect; allow February 30 or April 31 @TODO?
if (month < 1 || month > 12 || day < 1 || day > 31) {
this.throwError("date out of range");
}

const endDate = (new Date(year, month - 1, day)).getTime() / 1000;

return Math.ceil(endDate - startDate);
}

async prepareOptions(argParser: ArgParser): Promise<void> {
await super.prepareOptions(argParser);

if (this.accounts.length !== 1) {
this.throwError("new requires ONE account");
}

const timespans = argParser.consumeMultiOptions([ "duration", "until" ]);

if (timespans.length === 1) {
const timespan = timespans.pop();
if (timespan.name === "duration") {
this.duration = parseInt(timespan.value) * 60 * 60 * 24;
} else if (timespan.name === "until") {
this.until = timespan.value;
}
} else if (timespans.length > 1) {
this.throwError("renew requires at most ONE of --duration or --until");
} else {
this.duration = 365 * 60 * 60 * 24;
}
}

async prepareArgs(args: Array<string>): Promise<void> {
await super.prepareArgs(args);
const labels: Array<string> = [ ];
args.forEach((arg) => {
const comps = arg.split(".");
if (comps.length !== 2 || comps[1] !== "eth") {
this.throwError(`name not supported ${ JSON.stringify(arg) }`);
}
labels.push(comps[0]);
});

this.labels = Object.freeze(labels);
}

async run(): Promise<void> {
await super.run();

const ethController = await this.getEthController();
const ethRegistrar = await this.getEthRegistrar();

for (let i = 0; i < this.labels.length; i++) {
const label = this.labels[i];
console.log(label);

const expiration = (await ethRegistrar.nameExpires(ethers.utils.id(label))).toNumber();
if (expiration === 0) {
this.throwError(`not registered: ${ label }`);
}

const duration = this.duration ? this.duration: this.getDuration(expiration, this.until);
if (duration < 0) {
this.throwError(`bad duration: ${ duration }`);
}

const fee = (await ethController.rentPrice(label, duration)).mul(11).div(10);

this.dump(`Renew: ${ label }.eth`, {
"Current Expiry": formatDate(new Date(expiration * 1000)),
"Duration": `${ (duration / (24 * 60 * 60)) } days`,
"Until": formatDate(new Date((expiration + duration) * 1000)),
"Fee": `${ ethers.utils.formatEther(fee) } (+10% buffer)`,
});

await ethController.renew(label, duration, {
value: fee
});
}
}
}
cli.addPlugin("renew", RenewPlugin);

/**
* To Do:
* register NAME --registrar
Expand Down

0 comments on commit 54dfb75

Please sign in to comment.