Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Commit

Permalink
Merge pull request #3 from FrancoAguzzi/feat/remove-.eth-logics
Browse files Browse the repository at this point in the history
feat: Remove .eth related logics
  • Loading branch information
FrancoAguzzi authored Mar 13, 2024
2 parents 3ed3de6 + 3a7d25e commit 7a22e0a
Show file tree
Hide file tree
Showing 3 changed files with 1 addition and 264 deletions.
96 changes: 1 addition & 95 deletions src/price.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
import { describe, it, expect } from "vitest";

import {
PREMIUM_OFFSET,
PREMIUM_START_PRICE,
Price,
convertCurrencyWithRates,
formattedPrice,
subtractPrices,
temporaryPremiumPriceAtTimestamp,
} from "./price";
import { Price, convertCurrencyWithRates, formattedPrice } from "./price";
import { Currency, PriceCurrencyFormat } from "./currency";
import { GRACE_PERIOD, ONE_DAY_IN_SECONDS } from "./time";

enum CurrencyTestScenario {
"UNDERFLOW",
Expand Down Expand Up @@ -530,88 +521,3 @@ describe("Currencies overflow values displaying", () => {
expect(result.output).toBe(result.expectedOutput);
});
});

describe("Should correctly calculate premium prices for:", () => {
it("A domain that was released to the market 20 days ago", () => {
const hardcodedNow = 1707054623n; // 2024-02-04 13:50:23 UTC
const exampleExpirationTime = hardcodedNow - ONE_DAY_IN_SECONDS * 20n; // 20 days before hardcodedNow

const result = temporaryPremiumPriceAtTimestamp(
hardcodedNow,
exampleExpirationTime - GRACE_PERIOD
);

expect(result).toStrictEqual({
value: 4768n,
currency: Currency.Usd,
});
});

it("A domain that was released to the market 20 days and a half ago", () => {
const hardcodedNow = 1707054623n; // 2024-02-04 13:50:23 UTC
const exampleExpirationTime =
hardcodedNow - (ONE_DAY_IN_SECONDS * 41n) / 2n; // 20.5 days before hardcodedNow

const result = temporaryPremiumPriceAtTimestamp(
hardcodedNow,
exampleExpirationTime - GRACE_PERIOD
);

expect(result).toStrictEqual({
value: 1975n,
currency: Currency.Usd,
});
});

it("A domain that was released to the market 1 day and a half ago", () => {
const hardcodedNow = 1707054623n; // 2024-02-04 13:50:23 UTC
const expirationTime = hardcodedNow - (ONE_DAY_IN_SECONDS * 3n) / 2n; // 1.5 days before hardcodedNow
console.log("exactly 1.5 days ago - expirationTime: ", expirationTime);
const result = temporaryPremiumPriceAtTimestamp(
hardcodedNow,
expirationTime - GRACE_PERIOD
);

expect(result).toStrictEqual({
value: 3535529137n,
currency: Currency.Usd,
});
});

it("A domain that was released to the market 20 days, 23 hours and 59 minutes ago", () => {
const hardcodedNow = 1707054623n; // 2024-02-04 13:50:23 UTC
const TWENTY_DAYS_TWENTY_THREE_HOURS_TWENTY_NINE_MINUTES_IN_SECONDS =
1814340n;
const expirationTime =
hardcodedNow -
TWENTY_DAYS_TWENTY_THREE_HOURS_TWENTY_NINE_MINUTES_IN_SECONDS; // 1 minute from not having a premium price

const result = temporaryPremiumPriceAtTimestamp(
hardcodedNow,
expirationTime - GRACE_PERIOD
);

expect(result).toStrictEqual({
value: 2n,
currency: Currency.Usd,
});
});

it("A domain that was just now released to the market", () => {
const hardcodedNow = 1707054623n;
const expirationTime = hardcodedNow; // Exactly at expiration
console.log(
"exactly at expiration - exampleExpirationTime: ",
expirationTime
);
const result = temporaryPremiumPriceAtTimestamp(
hardcodedNow,
expirationTime - GRACE_PERIOD
);

// Expect full premium value (which is not $100M, but, $100M - PREMIUM_OFFSET instead)
expect(result).toStrictEqual(
subtractPrices(PREMIUM_START_PRICE, PREMIUM_OFFSET)
);
});
});
69 changes: 0 additions & 69 deletions src/price.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { Currency, PriceCurrencyFormat } from "./currency";
import { approxScaleBigInt } from "./number";
import {
GRACE_PERIOD,
ONE_DAY_IN_SECONDS,
TEMPORARY_PREMIUM_DAYS,
} from "./time";

export type Price = {
value: bigint;
Expand Down Expand Up @@ -184,67 +179,3 @@ export const convertCurrencyWithRates = (

return exchangedValuePrice;
};

export function temporaryPremiumPriceAtTimestamp(
atTimestamp: bigint,
expirationTimestamp: bigint
): Price {
const releasedTimestamp = expirationTimestamp + GRACE_PERIOD;
const secondsSinceRelease = atTimestamp - releasedTimestamp;
if (secondsSinceRelease < 0) {
// if as of the moment of `atTimestamp` a name hasn't expired yet then there is no temporaryPremium
return {
value: 0n,
currency: Currency.Usd,
};
}

const fractionalDaysSinceRelease =
Number(secondsSinceRelease) / Number(ONE_DAY_IN_SECONDS);

const decayFactor = PREMIUM_DECAY ** fractionalDaysSinceRelease;

const decayedPrice = approxScalePrice(PREMIUM_START_PRICE, decayFactor);
const offsetDecayedPrice = subtractPrices(decayedPrice, PREMIUM_OFFSET);

// the temporary premium can never be less than $0.00
if (offsetDecayedPrice.value < 0n) {
return {
value: 0n,
currency: Currency.Usd,
};
}

return offsetDecayedPrice;
}

/**
* At the moment a .eth name expires, this recently released temporary premium is added to its price.
* NOTE: The actual recently released temporary premium added subtracts `PREMIUM_OFFSET`.
*/
export const PREMIUM_START_PRICE: Price = {
value: 10000000000n, // $100,000,000.00 (100 million USD)
currency: Currency.Usd,
};

/**
* The recently released temporary premium drops exponentially by 50% each day.
*/
export const PREMIUM_DECAY = 0.5;

/**
* Goal:
* The temporary premium should drop to $0.00 after exactly `PREMIUM_DAYS` days have passed.
*
* Challenge:
* If we decay `PREMIUM_START` by a rate of `PREMIUM_DECAY` each day over the course of
* `PREMIUM_DAYS` days we don't get $0.00 USD. Instead, we get this `PREMIUM_OFFSET` value
* ($47.68 USD).
*
* Solution:
* Subtract this value from the decayed temporary premium to get the actual temporary premium.
*/
export const PREMIUM_OFFSET = approxScalePrice(
PREMIUM_START_PRICE,
PREMIUM_DECAY ** Number(TEMPORARY_PREMIUM_DAYS)
);
100 changes: 0 additions & 100 deletions src/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,13 @@ import {

import { bigIntToNumber } from "./number";

export enum PrimaryRegistrationStatus {
Active = "Active",
Expired = "Expired",
NeverRegistered = "NeverRegistered",
}

export enum SecondaryRegistrationStatus {
ExpiringSoon = "ExpiringSoon",
FullyReleased = "FullyReleased",
GracePeriod = "GracePeriod",
RecentlyReleased = "RecentlyReleased",
}

export type Registration = {
// Below timestamps are counted in seconds
registrationTimestamp: bigint | null;
expirationTimestamp: bigint | null;
expiryTimestamp: bigint | null;

primaryStatus: PrimaryRegistrationStatus;
secondaryStatus: SecondaryRegistrationStatus | null;
};

export const SECONDS_PER_YEAR = 31556952;

export const ONE_MINUTE_IN_SECONDS = 60n;
export const ONE_HOUR_IN_SECONDS = 60n * ONE_MINUTE_IN_SECONDS;
export const ONE_DAY_IN_SECONDS = 24n * ONE_HOUR_IN_SECONDS;
export const ONE_WEEK_IN_SECONDS = 7n * ONE_DAY_IN_SECONDS;

export const GRACE_PERIOD = 90n * ONE_DAY_IN_SECONDS;

export const TEMPORARY_PREMIUM_DAYS = 21n;

/**
* Converts milliseconds to seconds.
* @param ms: bigint - The milliseconds to convert.
Expand Down Expand Up @@ -161,76 +134,3 @@ export function prettyTimestampDiffFromNow(timestamp: bigint): string {
return "less than an hour";
}
}

/**
* Returns the expiration timestamp of a domain
* @param registration Registration object from domain
* @returns bigint | null
*/
export function domainExpirationTimestamp(
registration: Registration
): bigint | null {
if (registration.expirationTimestamp) {
return registration.expirationTimestamp;
}
return null;
}

/**
* Returns the release timestamp of a domain, which is 90 days after expiration when the Grace Period ends
* @param registration Registration object from domain
* @returns bigint | null
*/
export function domainReleaseTimestamp(
registration: Registration
): bigint | null {
const expirationTimestamp = domainExpirationTimestamp(registration);
if (expirationTimestamp === null) return null;

const releaseTimestamp = expirationTimestamp + GRACE_PERIOD;
return releaseTimestamp;
}

export enum OfferExpirationStatus {
Active,
ExpiringSoon,
Expired,
}

/**
* Evaluates and returns the expiration status of an offer based on its expiry timestamp.
* @param offerExpiry: bigint - The offer's expiry timestamp.
* @returns OfferExpirationStatus - The current status of the offer, indicating if it is active, expiring soon, or expired.
*/
export const getOfferExpirationStatus = (
offerExpiry: bigint
): OfferExpirationStatus => {
const nowTime = now();

const expired = offerExpiry < nowTime;

if (expired) return OfferExpirationStatus.Expired;

const expiringSoon = offerExpiry - nowTime < ONE_WEEK_IN_SECONDS;

if (expiringSoon) return OfferExpirationStatus.ExpiringSoon;

return OfferExpirationStatus.Active;
};

/**
* Evaluates and returns the expiration status of an offer based on its expiry timestamp.
* @param registrationPeriod: number - The number of years the registration is valid for.
* @returns renewalDate: Date - The date when the registration will expire.
*/
export const getRenewalDateAfterRegistration = (
registrationPeriod: number
): Date => {
const registrationRenewalDate = new Date();

registrationRenewalDate.setFullYear(
registrationRenewalDate.getFullYear() + registrationPeriod
);

return registrationRenewalDate;
};

0 comments on commit 7a22e0a

Please sign in to comment.