Skip to content

Commit

Permalink
fix: complete sat ordinal data
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelcr committed Feb 17, 2023
1 parent ff7608b commit 56389b5
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 56 deletions.
12 changes: 9 additions & 3 deletions src/api/routes/sats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Type } from '@sinclair/typebox';
import { FastifyPluginCallback } from 'fastify';
import { Server } from 'http';
import { NotFoundResponse, OrdinalParam, SatoshiResponse } from '../types';
import { getOrdinalSatoshi } from '../util/ordinal-sats';
import { OrdinalSatoshi } from '../util/ordinal-satoshi';

export const SatRoutes: FastifyPluginCallback<Record<never, never>, Server, TypeBoxTypeProvider> = (
fastify,
Expand All @@ -27,13 +27,19 @@ export const SatRoutes: FastifyPluginCallback<Record<never, never>, Server, Type
},
},
async (request, reply) => {
const sat = getOrdinalSatoshi(request.params.ordinal);
const sat = new OrdinalSatoshi(request.params.ordinal);
const inscription = await fastify.db.getInscription({ ordinal: request.params.ordinal });
await reply.send({
block_height: sat.block_height,
coinbase_height: sat.blockHeight,
cycle: sat.cycle,
epoch: sat.epoch,
period: sat.period,
offset: sat.offset,
decimal: sat.decimal,
degree: sat.degree,
name: sat.name,
rarity: sat.rarity,
percentile: sat.percentile,
inscription_id: inscription?.inscription_id,
});
}
Expand Down
15 changes: 8 additions & 7 deletions src/api/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Static, TSchema, Type } from '@sinclair/typebox';
import { SatoshiRarity } from './util/ordinal-satoshi';

const BitcoinAddressRegEx = /(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}/;
export const BitcoinAddressParam = Type.RegEx(BitcoinAddressRegEx);
Expand Down Expand Up @@ -42,17 +43,17 @@ export const InscriptionResponse = Type.Object({
export type InscriptionResponseType = Static<typeof InscriptionResponse>;

export const SatoshiResponse = Type.Object({
block_height: Type.Integer(),
coinbase_height: Type.Integer(),
cycle: Type.Integer(),
decimal: Type.String(),
degree: Type.String(),
inscription_id: Type.Optional(Type.String()),
// epoch: Type.Number(),
// name: Type.String(),
// offset: Type.String(),
// percentile: Type.String(),
// period: Type.Integer(),
// rarity: 'common',
epoch: Type.Number(),
name: Type.String(),
offset: Type.Number(),
percentile: Type.String(),
period: Type.Integer(),
rarity: Type.Enum(SatoshiRarity),
// timestamp: Type.Integer(),
});

Expand Down
98 changes: 98 additions & 0 deletions src/api/util/ordinal-satoshi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
const HALVING_BLOCKS = 210_000;
const DIFFICULTY_ADJUST_BLOCKS = 2016;
const INITIAL_SUBSIDY = 50;
const SATS_PER_BTC = 100_000_000;
const SAT_SUPPLY = 2099999997690000;

export enum SatoshiRarity {
common = 'common',
uncommon = 'uncommon',
rare = 'rare',
epic = 'epic',
legendary = 'legendary',
mythic = 'mythic',
}

export class OrdinalSatoshi {
public blockHeight: number;
public cycle: number;
public ordinal: number;
public epoch: number;
public period: number;
public offset: number;
private hour: number;
private minute: number;
private second: number;
private third: number;

constructor(ordinal: number) {
let satAccum = 0;
let subsidy = INITIAL_SUBSIDY;
let epoch = 0;
while (true) {
const satHalvingMax = HALVING_BLOCKS * subsidy * SATS_PER_BTC;
if (satAccum + satHalvingMax > ordinal) {
break;
}
satAccum += satHalvingMax;
subsidy /= 2;
epoch++;
}
const halvingOffset = ordinal - satAccum;
const exactHeight = halvingOffset / (subsidy * SATS_PER_BTC) + epoch * HALVING_BLOCKS;

this.ordinal = ordinal;
this.blockHeight = Math.floor(exactHeight);
this.cycle = this.hour = Math.floor(epoch / 6);
this.minute = this.blockHeight % (epoch * HALVING_BLOCKS);
this.second = this.blockHeight % DIFFICULTY_ADJUST_BLOCKS;
this.third = this.offset = Math.round(
(exactHeight - this.blockHeight) * subsidy * Math.pow(10, 8)
);
this.epoch = epoch;
this.period = Math.floor(this.blockHeight / DIFFICULTY_ADJUST_BLOCKS);
}

public get degree(): string {
return `${this.hour}°${this.minute}${this.second}${this.third}‴`;
}

public get decimal(): string {
return `${this.blockHeight}.${this.third}`;
}

public get name(): string {
let x = SAT_SUPPLY - this.ordinal;
const name: string[] = [];
const alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
while (x > 0) {
const index = Math.floor((x - 1) % 26);
name.push(alphabet[index]);
x = (x - 1) / 26;
}
return name.reverse().join('');
}

public get percentile(): string {
return `${(this.ordinal / (SAT_SUPPLY - 1)) * 100.0}%`;
}

public get rarity(): SatoshiRarity {
if (this.hour === 0 && this.minute === 0 && this.second === 0 && this.third === 0) {
return SatoshiRarity.mythic;
}
if (this.minute === 0 && this.second === 0 && this.third === 0) {
return SatoshiRarity.legendary;
}
if (this.minute === 0 && this.third === 0) {
return SatoshiRarity.epic;
}
if (this.second === 0 && this.third === 0) {
return SatoshiRarity.rare;
}
if (this.third === 0) {
return SatoshiRarity.uncommon;
}
return SatoshiRarity.common;
}
}
46 changes: 0 additions & 46 deletions src/api/util/ordinal-sats.ts

This file was deleted.

0 comments on commit 56389b5

Please sign in to comment.