Merge pull request #434 from hirosystems/develop

release to beta
This commit is contained in:
Rafael Cárdenas
2025-02-18 11:37:46 -06:00
committed by GitHub
19 changed files with 339 additions and 170 deletions

View File

@@ -342,6 +342,7 @@ export const InscriptionResponse = Type.Object(
examples: ['brc20'],
})
),
charms: Type.Array(Type.String({ examples: ['coin', 'palindrome', 'vindicated'] })),
},
{ title: 'Inscription Response' }
);

View File

@@ -31,6 +31,37 @@ function parseTimestamp(timestamp: number): number {
return timestamp * 1000;
}
enum Charm {
coin = 0,
cursed = 1,
epic = 2,
legendary = 3,
lost = 4,
nineball = 5,
rare = 6,
reinscription = 7,
unbound = 8,
uncommon = 9,
vindicated = 10,
mythic = 11,
burned = 12,
palindrome = 13,
}
function parseCharms(charms: string): string[] {
const charmsVal = parseInt(charms);
const result: Charm[] = [];
for (const charm in Charm) {
if (!isNaN(Number(charm))) {
const charmValue = Number(charm);
if (charmsVal & (1 << charmValue)) {
result.push(charmValue as Charm);
}
}
}
return result.map(charm => Charm[charm]);
}
export function parseDbInscriptions(
items: DbFullyLocatedInscriptionResult[]
): InscriptionResponseType[] {
@@ -63,6 +94,7 @@ export function parseDbInscriptions(
metadata: i.metadata ? JSON.parse(i.metadata) : null,
delegate: i.delegate ?? null,
meta_protocol: i.metaprotocol ?? null,
charms: parseCharms(i.charms),
}));
}
export function parseDbInscription(item: DbFullyLocatedInscriptionResult): InscriptionResponseType {

View File

@@ -190,6 +190,7 @@ export class PgStore extends BasePgStore {
i.tx_index AS genesis_tx_index,
i.timestamp AS genesis_timestamp,
i.address AS genesis_address,
i.charms,
cur.address,
cur.tx_index,
cur.block_height,

View File

@@ -37,6 +37,7 @@ export type DbFullyLocatedInscriptionResult = {
pointer: number | null;
metaprotocol: string | null;
delegate: string | null;
charms: string;
};
export type DbLocation = {

View File

@@ -65,6 +65,7 @@ describe('ETag cache', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '9000',
charms: 0,
});
const response = await fastify.inject({
method: 'GET',
@@ -165,6 +166,7 @@ describe('ETag cache', () => {
prev_offset: null,
transfer_type: 'transferred',
rarity: 'common',
charms: 0,
});
await inscriptionReveal(db.sql, {
content: '0x48656C6C6F',
@@ -197,6 +199,7 @@ describe('ETag cache', () => {
prev_offset: null,
transfer_type: 'transferred',
rarity: 'common',
charms: 0,
});
// ETag response
@@ -277,6 +280,7 @@ describe('ETag cache', () => {
prev_offset: null,
transfer_type: 'transferred',
rarity: 'common',
charms: 0,
});
// ETag response
@@ -328,6 +332,7 @@ describe('ETag cache', () => {
prev_offset: null,
transfer_type: 'transferred',
rarity: 'common',
charms: 0,
});
// Cache busted
@@ -371,6 +376,7 @@ describe('ETag cache', () => {
prev_offset: null,
transfer_type: 'transferred',
rarity: 'common',
charms: 0,
});
// ETag response
@@ -422,6 +428,7 @@ describe('ETag cache', () => {
prev_offset: null,
transfer_type: 'transferred',
rarity: 'common',
charms: 0,
});
// Cache busted

View File

@@ -68,6 +68,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '51483',
charms: 10369,
});
const expected = {
address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td',
@@ -98,6 +99,7 @@ describe('/inscriptions', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: ['coin', 'reinscription', 'mythic', 'palindrome'],
};
// By inscription id
@@ -154,6 +156,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '51483',
charms: 0,
});
await insertTestInscriptionRecursion(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -200,6 +203,7 @@ describe('/inscriptions', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: [],
};
// By inscription id
@@ -251,6 +255,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: 'f351d86c6e6cae3c64e297e7463095732f216875bcc1f3c03f950a492bb25421i0',
@@ -283,6 +288,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '51483',
charms: 0,
});
await insertTestInscriptionParent(db.sql, {
inscription_id: 'f351d86c6e6cae3c64e297e7463095732f216875bcc1f3c03f950a492bb25421i0',
@@ -330,6 +336,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response = await fastify.inject({
method: 'GET',
@@ -371,6 +378,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '51483',
charms: 0,
});
const expected = {
address: '',
@@ -401,6 +409,7 @@ describe('/inscriptions', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: [],
};
// By inscription id
@@ -452,6 +461,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '51483',
charms: 0,
});
const expected = {
address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td',
@@ -482,6 +492,7 @@ describe('/inscriptions', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: [],
};
// By inscription id
@@ -533,6 +544,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '51483',
charms: 0,
});
// Transfer 1
@@ -590,6 +602,7 @@ describe('/inscriptions', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: [],
});
// Transfer 2
@@ -647,6 +660,7 @@ describe('/inscriptions', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: [],
});
});
@@ -682,6 +696,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '51483',
charms: 0,
});
// Multiple transfers
@@ -759,6 +774,7 @@ describe('/inscriptions', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: [],
});
});
@@ -794,6 +810,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '51483',
charms: 0,
});
// Transfer 1
@@ -851,6 +868,7 @@ describe('/inscriptions', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: [],
});
// Transfer 2
@@ -908,6 +926,7 @@ describe('/inscriptions', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: [],
});
});
@@ -943,6 +962,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '51483',
charms: 0,
});
const response = await fastify.inject({
method: 'GET',
@@ -985,6 +1005,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '51483',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '42174ecc8a245841035793390bb53d63b3c2acb61366446f601b09e73b94b656i0',
@@ -1017,6 +1038,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '51483',
charms: 0,
});
const response = await fastify.inject({
method: 'GET',
@@ -1061,6 +1083,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
// Transfer 1
@@ -1213,6 +1236,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '7ac73ecd01b9da4a7eab904655416dbfe8e03f193e091761b5a63ad0963570cdi0',
@@ -1245,6 +1269,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
// No transfers on this block because they are all genesis.
@@ -1573,6 +1598,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -1605,6 +1631,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response1 = await fastify.inject({
@@ -1644,6 +1671,7 @@ describe('/inscriptions', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: [],
},
{
address: 'bc1pscktlmn99gyzlvymvrezh6vwd0l4kg06tg5rvssw0czg8873gz5sdkteqj',
@@ -1674,6 +1702,7 @@ describe('/inscriptions', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: [],
},
]);
});
@@ -1711,6 +1740,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -1743,6 +1773,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response1 = await fastify.inject({
@@ -1782,6 +1813,7 @@ describe('/inscriptions', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: [],
};
expect(responseJson1.results[0]).toStrictEqual(result1);
@@ -1822,6 +1854,7 @@ describe('/inscriptions', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: [],
};
expect(responseJson2.results[0]).toStrictEqual(result2);
@@ -1869,6 +1902,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -1901,6 +1935,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'mythic',
coinbase_height: '0',
charms: 0,
});
const response1 = await fastify.inject({
@@ -1963,6 +1998,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -1995,6 +2031,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response1 = await fastify.inject({
@@ -2060,6 +2097,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -2092,6 +2130,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response1 = await fastify.inject({
@@ -2153,6 +2192,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -2185,6 +2225,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response1 = await fastify.inject({
@@ -2248,6 +2289,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response4 = await fastify.inject({
method: 'GET',
@@ -2293,6 +2335,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -2325,6 +2368,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response1 = await fastify.inject({
@@ -2372,6 +2416,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -2404,6 +2449,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response2 = await fastify.inject({
@@ -2459,6 +2505,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -2491,6 +2538,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response2 = await fastify.inject({
@@ -2546,6 +2594,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '51483',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -2578,6 +2627,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '200',
charms: 0,
});
const response2 = await fastify.inject({
@@ -2633,6 +2683,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -2665,6 +2716,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response2 = await fastify.inject({
@@ -2719,6 +2771,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -2751,6 +2804,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response1 = await fastify.inject({
@@ -2797,6 +2851,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -2829,6 +2884,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response1 = await fastify.inject({
@@ -2885,6 +2941,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -2919,6 +2976,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await insertTestInscriptionRecursion(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -2982,6 +3040,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -3014,6 +3073,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response1 = await fastify.inject({
@@ -3073,6 +3133,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -3105,6 +3166,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
const response1 = await fastify.inject({
@@ -3163,6 +3225,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -3195,6 +3258,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '567c7605439dfdc3a289d13fd2132237852f4a56e784b9364ba94499d5f9baf1i0',
@@ -3227,6 +3291,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '0',
charms: 0,
});
const response1 = await fastify.inject({
@@ -3284,6 +3349,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -3316,6 +3382,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'epic',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '567c7605439dfdc3a289d13fd2132237852f4a56e784b9364ba94499d5f9baf1i0',
@@ -3348,6 +3415,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'mythic',
coinbase_height: '0',
charms: 0,
});
const response1 = await fastify.inject({
@@ -3405,6 +3473,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -3437,6 +3506,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '567c7605439dfdc3a289d13fd2132237852f4a56e784b9364ba94499d5f9baf1i0',
@@ -3469,6 +3539,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '0',
charms: 0,
});
const response1 = await fastify.inject({
@@ -3526,6 +3597,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '38c46a8bf7ec90bc7f6b797e7dc84baa97f4e5fd4286b92fe1b50176d03b18dci0',
@@ -3558,6 +3630,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: '567c7605439dfdc3a289d13fd2132237852f4a56e784b9364ba94499d5f9baf1i0',
@@ -3590,6 +3663,7 @@ describe('/inscriptions', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '0',
charms: 0,
});
const response1 = await fastify.inject({

View File

@@ -84,6 +84,7 @@ describe('/sats', () => {
prev_offset: null,
transfer_type: 'transferred',
rarity: 'common',
charms: 0,
});
const response = await fastify.inject({
method: 'GET',
@@ -127,6 +128,7 @@ describe('/sats', () => {
prev_offset: null,
transfer_type: 'transferred',
rarity: 'common',
charms: 0,
});
await inscriptionReveal(db.sql, {
content: '0x48656C6C6F',
@@ -160,6 +162,7 @@ describe('/sats', () => {
prev_offset: null,
transfer_type: 'transferred',
rarity: 'common',
charms: 0,
});
// Simulate the inscription transfer for -7
await inscriptionTransfer(db.sql, {
@@ -219,6 +222,7 @@ describe('/sats', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: [],
},
{
address: 'bc1p3cyx5e2hgh53w7kpxcvm8s4kkega9gv5wfw7c4qxsvxl0u8x834qf0u2td',
@@ -250,6 +254,7 @@ describe('/sats', () => {
metadata: null,
meta_protocol: null,
delegate: null,
charms: [],
},
]);

View File

@@ -77,6 +77,7 @@ describe('Status', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await inscriptionReveal(db.sql, {
inscription_id: 'a98d7055a77fa0b96cc31e30bb8bacf777382d1b67f1b7eca6f2014e961591c8i0',
@@ -109,6 +110,7 @@ describe('Status', () => {
transfer_type: 'transferred',
rarity: 'common',
coinbase_height: '650000',
charms: 0,
});
await updateTestChainTip(db.sql, 791975);

View File

@@ -77,6 +77,7 @@ type TestOrdinalsInscriptionsRow = {
metaprotocol: string | null;
delegate: string | null;
timestamp: number;
charms: number;
};
async function insertTestInscription(sql: PgSqlClient, row: TestOrdinalsInscriptionsRow) {
await sql`INSERT INTO inscriptions ${sql(row)}`;
@@ -230,6 +231,7 @@ export async function inscriptionReveal(sql: PgSqlClient, reveal: TestOrdinalsIn
metaprotocol: reveal.metaprotocol,
delegate: reveal.delegate,
timestamp: reveal.timestamp,
charms: reveal.charms,
});
await insertTestLocation(sql, {
ordinal_number: reveal.ordinal_number,

View File

@@ -39,45 +39,6 @@ pub enum OrdinalInscriptionCurseType {
Generic,
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct OrdinalInscriptionCharms {
pub coin: bool,
pub cursed: bool,
pub epic: bool,
pub legendary: bool,
pub lost: bool,
pub nineball: bool,
pub rare: bool,
pub reinscription: bool,
pub unbound: bool,
pub uncommon: bool,
pub vindicated: bool,
pub mythic: bool,
pub burned: bool,
pub palindrome: bool,
}
impl OrdinalInscriptionCharms {
pub fn none() -> Self {
OrdinalInscriptionCharms {
coin: false,
cursed: false,
epic: false,
legendary: false,
lost: false,
nineball: false,
rare: false,
reinscription: false,
unbound: false,
uncommon: false,
vindicated: false,
mythic: false,
burned: false,
palindrome: false,
}
}
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct OrdinalInscriptionRevealData {
pub content_bytes: String,
@@ -101,7 +62,7 @@ pub struct OrdinalInscriptionRevealData {
pub transfers_pre_inscription: u32,
pub satpoint_post_inscription: String,
pub curse_type: Option<OrdinalInscriptionCurseType>,
pub charms: OrdinalInscriptionCharms,
pub charms: u16,
}
impl OrdinalInscriptionNumber {

View File

@@ -1,7 +1,7 @@
use chainhook_sdk::utils::Context;
use chainhook_types::{
OrdinalInscriptionCharms, OrdinalInscriptionNumber, OrdinalInscriptionRevealData,
OrdinalInscriptionTransferData, OrdinalInscriptionTransferDestination,
OrdinalInscriptionNumber, OrdinalInscriptionRevealData, OrdinalInscriptionTransferData,
OrdinalInscriptionTransferDestination,
};
pub fn get_test_ctx() -> Context {
@@ -88,7 +88,7 @@ impl Brc20RevealBuilder {
satpoint_post_inscription:
"9bb2314d666ae0b1db8161cb373fcc1381681f71445c4e0335aa80ea9c37fcdd:0:0".to_string(),
curse_type: None,
charms: OrdinalInscriptionCharms::none(),
charms: 0,
}
}
}

View File

@@ -25,7 +25,7 @@ use crate::{
protocol::{
inscription_parsing::parse_inscriptions_in_standardized_block,
inscription_sequencing::{
augment_block_with_inscriptions, get_bitcoin_network, get_jubilee_block_height,
update_block_inscriptions_with_consensus_sequence_data, get_bitcoin_network, get_jubilee_block_height,
parallelize_inscription_data_computations,
},
satoshi_numbering::TraversalResult,
@@ -224,7 +224,7 @@ pub async fn index_block(
ctx,
)?;
if has_inscription_reveals {
augment_block_with_inscriptions(block, sequence_cursor, cache_l1, &ord_tx, ctx)
update_block_inscriptions_with_consensus_sequence_data(block, sequence_cursor, cache_l1, &ord_tx, ctx)
.await?;
}
augment_block_with_transfers(block, &ord_tx, ctx).await?;

View File

@@ -3,8 +3,8 @@ use bitcoin::Witness;
use chainhook_sdk::utils::Context;
use chainhook_types::{
BitcoinBlockData, BitcoinNetwork, BitcoinTransactionData, BlockIdentifier,
OrdinalInscriptionCharms, OrdinalInscriptionCurseType, OrdinalInscriptionNumber,
OrdinalInscriptionRevealData, OrdinalInscriptionTransferData, OrdinalOperation,
OrdinalInscriptionCurseType, OrdinalInscriptionNumber, OrdinalInscriptionRevealData,
OrdinalOperation,
};
use serde_json::json;
use std::collections::HashMap;
@@ -102,7 +102,7 @@ pub fn parse_inscriptions_from_witness(
transfers_pre_inscription: 0,
satpoint_post_inscription: format!(""),
curse_type,
charms: OrdinalInscriptionCharms::none(),
charms: 0,
};
inscriptions.push((reveal_data, envelope.payload));
}
@@ -169,90 +169,19 @@ pub fn parse_inscriptions_in_standardized_block(
}
}
pub fn get_inscriptions_revealed_in_block(
block: &BitcoinBlockData,
) -> Vec<&OrdinalInscriptionRevealData> {
let mut ops = vec![];
for tx in block.transactions.iter() {
for op in tx.metadata.ordinal_operations.iter() {
if let OrdinalOperation::InscriptionRevealed(op) = op {
ops.push(op);
}
}
}
ops
}
pub fn get_inscriptions_transferred_in_block(
block: &BitcoinBlockData,
) -> Vec<&OrdinalInscriptionTransferData> {
let mut ops = vec![];
for tx in block.transactions.iter() {
for op in tx.metadata.ordinal_operations.iter() {
if let OrdinalOperation::InscriptionTransferred(op) = op {
ops.push(op);
}
}
}
ops
}
#[cfg(test)]
mod test {
use std::collections::HashMap;
use chainhook_sdk::utils::Context;
use chainhook_types::{
BitcoinBlockData, BitcoinTransactionData, OrdinalInscriptionTransferData,
OrdinalInscriptionTransferDestination, OrdinalOperation,
};
use test_case::test_case;
use chainhook_types::OrdinalOperation;
use crate::{
config::Config,
core::test_builders::{TestBlockBuilder, TestTransactionBuilder, TestTxInBuilder},
};
use super::{
get_inscriptions_revealed_in_block, get_inscriptions_transferred_in_block,
parse_inscriptions_in_standardized_block,
};
pub fn new_test_transfer_tx_with_operation() -> BitcoinTransactionData {
TestTransactionBuilder::new()
.ordinal_operations(vec![OrdinalOperation::InscriptionTransferred(
OrdinalInscriptionTransferData {
ordinal_number: 300144140535834,
destination: OrdinalInscriptionTransferDestination::Transferred(
"bc1pcwway0ne322s0lrc5e905f3chuclvnyy3z6wn86azkgmgcprf3tqvyy7ws"
.to_string(),
),
satpoint_pre_transfer:
"ab2683db34e335c89a5c1d634e6c5bd8d8bca8ded281be84f71f921c9e8783b2:0:0"
.to_string(),
satpoint_post_transfer:
"42fa098abab8d5cca1c303a97bd0404cf8e9b8faaab6dd228a309e66daff8fae:1:0"
.to_string(),
post_transfer_output_value: Some(546),
tx_index: 54,
},
)])
.build()
}
#[test_case(&TestBlockBuilder::new().build() => 0; "with empty block")]
#[test_case(&TestBlockBuilder::new().transactions(vec![TestTransactionBuilder::new_with_operation().build()]).build() => 1; "with reveal transaction")]
#[test_case(&TestBlockBuilder::new().transactions(vec![new_test_transfer_tx_with_operation()]).build() => 0; "with transfer transaction")]
fn gets_reveals_in_block(block: &BitcoinBlockData) -> usize {
get_inscriptions_revealed_in_block(block).len()
}
#[test_case(&TestBlockBuilder::new().build() => 0; "with empty block")]
#[test_case(&TestBlockBuilder::new().transactions(vec![TestTransactionBuilder::new_with_operation().build()]).build() => 0; "with reveal transaction")]
#[test_case(&TestBlockBuilder::new().transactions(vec![new_test_transfer_tx_with_operation()]).build() => 1; "with transfer transaction")]
fn gets_transfers_in_block(block: &BitcoinBlockData) -> usize {
get_inscriptions_transferred_in_block(block).len()
}
use super::parse_inscriptions_in_standardized_block;
#[test]
fn parses_inscriptions_in_block() {

View File

@@ -23,7 +23,7 @@ use crate::{
try_debug, try_error, try_info,
utils::format_inscription_id,
};
use ord::height::Height;
use ord::{charm::Charm, height::Height, sat::Sat};
use std::sync::mpsc::channel;
@@ -391,26 +391,25 @@ pub fn get_bitcoin_network(network: &BitcoinNetwork) -> Network {
/// Given a `BitcoinBlockData` that have been augmented with the functions `parse_inscriptions_in_raw_tx`,
/// `parse_inscriptions_in_standardized_tx` or `parse_inscriptions_and_standardize_block`, mutate the ordinals drafted
/// informations with actual, consensus data.
pub async fn augment_block_with_inscriptions(
pub async fn update_block_inscriptions_with_consensus_sequence_data(
block: &mut BitcoinBlockData,
sequence_cursor: &mut SequenceCursor,
inscriptions_data: &mut BTreeMap<(TransactionIdentifier, usize, u64), TraversalResult>,
db_tx: &Transaction<'_>,
ctx: &Context,
) -> Result<(), String> {
// Handle re-inscriptions
// Check if we've previously inscribed over any satoshi being inscribed to in this new block. This would be a reinscription.
let mut reinscriptions_data =
ordinals_pg::get_reinscriptions_for_block(inscriptions_data, db_tx).await?;
// Handle sat oveflows
let mut sats_overflows = VecDeque::new();
// Keep a reference of inscribed satoshis that fall outside of this block's total sats. These would be unbound inscriptions.
let mut sat_overflows = VecDeque::new();
let network = get_bitcoin_network(&block.metadata.network);
let coinbase_subsidy = Height(block.block_identifier.index as u32).subsidy();
let coinbase_tx = &block.transactions[0].clone();
let mut cumulated_fees = 0u64;
for (tx_index, tx) in block.transactions.iter_mut().enumerate() {
augment_transaction_with_ordinals_inscriptions_data(
update_tx_inscriptions_with_consensus_sequence_data(
tx,
tx_index,
&block.block_identifier,
@@ -420,7 +419,7 @@ pub async fn augment_block_with_inscriptions(
coinbase_tx,
coinbase_subsidy,
&mut cumulated_fees,
&mut sats_overflows,
&mut sat_overflows,
&mut reinscriptions_data,
db_tx,
ctx,
@@ -428,8 +427,7 @@ pub async fn augment_block_with_inscriptions(
.await?;
}
// Handle sats overflow
while let Some((tx_index, op_index)) = sats_overflows.pop_front() {
while let Some((tx_index, op_index)) = sat_overflows.pop_front() {
let OrdinalOperation::InscriptionRevealed(ref mut inscription_data) =
block.transactions[tx_index].metadata.ordinal_operations[op_index]
else {
@@ -455,13 +453,11 @@ pub async fn augment_block_with_inscriptions(
Ok(())
}
/// Given a `BitcoinTransactionData` that have been augmented with the functions `parse_inscriptions_in_raw_tx` or
/// `parse_inscriptions_in_standardized_tx`, mutate the ordinals drafted informations with actual, consensus data, by
/// using informations from `inscription_data` and `reinscription_data`.
/// Given a `BitcoinTransactionData` that have been augmented with `parse_inscriptions_in_standardized_tx`, mutate the ordinals
/// drafted informations with actual, consensus data, by using informations from `inscription_data` and `reinscription_data`.
///
/// Transactions are not fully correct from a consensus point of view state transient state after the execution of this
/// function.
async fn augment_transaction_with_ordinals_inscriptions_data(
/// Transactions are not fully correct from a consensus point of view state transient state after the execution of this function.
async fn update_tx_inscriptions_with_consensus_sequence_data(
tx: &mut BitcoinTransactionData,
tx_index: usize,
block_identifier: &BlockIdentifier,
@@ -476,18 +472,21 @@ async fn augment_transaction_with_ordinals_inscriptions_data(
db_tx: &Transaction<'_>,
ctx: &Context,
) -> Result<bool, String> {
let inputs = tx
if tx.metadata.ordinal_operations.is_empty() {
return Ok(false);
}
let tx_input_values = tx
.metadata
.inputs
.iter()
.map(|i| i.previous_output.value)
.collect::<Vec<u64>>();
let mut mut_operations = vec![];
mut_operations.append(&mut tx.metadata.ordinal_operations);
let any_event = tx.metadata.ordinal_operations.is_empty() == false;
let mut mutated_operations = vec![];
mutated_operations.append(&mut tx.metadata.ordinal_operations);
let mut inscription_subindex = 0;
for (op_index, op) in mutated_operations.iter_mut().enumerate() {
for (op_index, op) in mut_operations.iter_mut().enumerate() {
let (mut is_cursed, inscription) = match op {
OrdinalOperation::InscriptionRevealed(inscription) => {
(inscription.curse_type.as_ref().is_some(), inscription)
@@ -496,7 +495,7 @@ async fn augment_transaction_with_ordinals_inscriptions_data(
};
let (input_index, relative_offset) = match inscription.inscription_pointer {
Some(pointer) => resolve_absolute_pointer(&inputs, pointer),
Some(pointer) => resolve_absolute_pointer(&tx_input_values, pointer),
None => (inscription.inscription_input_index, 0),
};
@@ -506,38 +505,35 @@ async fn augment_transaction_with_ordinals_inscriptions_data(
match inscriptions_data.get(&(transaction_identifier, input_index, relative_offset)) {
Some(traversal) => traversal,
None => {
let err_msg = format!(
"Unable to retrieve backward traversal result for inscription {}",
return Err(format!(
"Unable to retrieve backward traversal result for inscription in tx {}",
tx.transaction_identifier.hash
);
try_error!(ctx, "{}", err_msg);
std::process::exit(1);
));
}
};
// Do we need to curse the inscription?
// Do we need to curse the inscription? Is this inscription re-inscribing an existing blessed inscription?
let mut inscription_number = sequence_cursor
.pick_next(is_cursed, block_identifier.index, network, db_tx)
.await?;
let mut curse_type_override = None;
if !is_cursed {
// Is this inscription re-inscribing an existing blessed inscription?
if let Some(exisiting_inscription_id) =
reinscriptions_data.get(&traversal.ordinal_number)
{
try_info!(
ctx,
"Satoshi #{} was inscribed with blessed inscription {}, cursing inscription {}",
"Satoshi {} was previously inscribed with blessed inscription {}, cursing inscription {}",
traversal.ordinal_number,
exisiting_inscription_id,
traversal.get_inscription_id(),
);
is_cursed = true;
inscription_number = sequence_cursor
.pick_next(is_cursed, block_identifier.index, network, db_tx)
.await?;
curse_type_override = Some(OrdinalInscriptionCurseType::Reinscription)
curse_type_override = Some(OrdinalInscriptionCurseType::Reinscription);
Charm::Reinscription.set(&mut inscription.charms);
}
};
@@ -564,8 +560,6 @@ async fn augment_transaction_with_ordinals_inscriptions_data(
cumulated_fees,
ctx,
);
// Compute satpoint_post_inscription
inscription.satpoint_post_inscription = satpoint_post_transfer;
inscription_subindex += 1;
@@ -579,17 +573,30 @@ async fn augment_transaction_with_ordinals_inscriptions_data(
// spent to fees are numbered as if they appear last in the block in which they
// are revealed.
sats_overflows.push_back((tx_index, op_index));
Charm::Unbound.set(&mut inscription.charms);
continue;
}
OrdinalInscriptionTransferDestination::Burnt(_) => {}
OrdinalInscriptionTransferDestination::Burnt(_) => {
Charm::Burned.set(&mut inscription.charms);
}
OrdinalInscriptionTransferDestination::Transferred(address) => {
inscription.inscription_output_value = output_value.unwrap_or(0);
inscription.inscriber_address = Some(address);
if output_value.is_none() {
Charm::Lost.set(&mut inscription.charms);
}
}
};
// The reinscriptions_data needs to be augmented as we go, to handle transaction chaining.
if !is_cursed {
inscription.charms |= Sat(traversal.ordinal_number).charms();
if is_cursed {
if block_identifier.index >= get_jubilee_block_height(network) {
Charm::Vindicated.set(&mut inscription.charms);
} else {
Charm::Cursed.set(&mut inscription.charms);
}
} else {
// The reinscriptions_data needs to be augmented as we go, to handle transaction chaining.
reinscriptions_data.insert(traversal.ordinal_number, traversal.get_inscription_id());
}
@@ -603,9 +610,147 @@ async fn augment_transaction_with_ordinals_inscriptions_data(
);
sequence_cursor.increment(is_cursed, db_tx).await?;
}
tx.metadata
.ordinal_operations
.append(&mut mutated_operations);
tx.metadata.ordinal_operations.append(&mut mut_operations);
Ok(any_event)
Ok(true)
}
#[cfg(test)]
mod test {
use std::collections::BTreeMap;
use test_case::test_case;
use chainhook_postgres::{pg_begin, pg_pool_client};
use chainhook_sdk::utils::Context;
use chainhook_types::{
bitcoin::{OutPoint, TxIn, TxOut},
OrdinalInscriptionCurseType, OrdinalInscriptionNumber, OrdinalInscriptionRevealData,
OrdinalOperation, TransactionIdentifier,
};
use ord::charm::Charm;
use crate::{
core::{
protocol::{satoshi_numbering::TraversalResult, sequence_cursor::SequenceCursor},
test_builders::{TestBlockBuilder, TestTransactionBuilder},
},
db::{ordinals_pg, pg_reset_db, pg_test_connection, pg_test_connection_pool},
};
use super::update_block_inscriptions_with_consensus_sequence_data;
#[test_case((884207, false, 1262349832364434, "0x5120694b38ea24908e86a857279105c376a82cd1556f51655abb2ebef398b57daa8b".into()) => Ok(vec![]); "common sat")]
#[test_case((884207, false, 0, "0x5120694b38ea24908e86a857279105c376a82cd1556f51655abb2ebef398b57daa8b".into()) => Ok(vec![Charm::Coin, Charm::Mythic, Charm::Palindrome]); "mythic sat")]
#[test_case((884207, false, 1050000000000000, "0x5120694b38ea24908e86a857279105c376a82cd1556f51655abb2ebef398b57daa8b".into()) => Ok(vec![Charm::Coin, Charm::Epic]); "epic sat")]
#[test_case((884207, false, 123454321, "0x5120694b38ea24908e86a857279105c376a82cd1556f51655abb2ebef398b57daa8b".into()) => Ok(vec![Charm::Palindrome]); "palindrome sat")]
#[test_case((884207, false, 1262349832364434, "0x00".into()) => Ok(vec![Charm::Burned]); "burned inscription")]
#[test_case((780000, true, 1262349832364434, "0x5120694b38ea24908e86a857279105c376a82cd1556f51655abb2ebef398b57daa8b".into()) => Ok(vec![Charm::Cursed]); "cursed inscription")]
#[test_case((884207, true, 1262349832364434, "0x5120694b38ea24908e86a857279105c376a82cd1556f51655abb2ebef398b57daa8b".into()) => Ok(vec![Charm::Vindicated]); "vindicated inscription")]
#[tokio::test]
async fn inscription_charms(
(block_height, cursed, ordinal_number, script_pubkey): (u64, bool, u64, String),
) -> Result<Vec<Charm>, String> {
let ctx = Context::empty();
let mut sequence_cursor = SequenceCursor::new();
let mut cache_l1 = BTreeMap::new();
let tx_id = TransactionIdentifier {
hash: "b4722ad74e7092a194e367f2ec0609994ef7a006db4f9b9d055b46cfb6514e06".into(),
};
cache_l1.insert(
(tx_id.clone(), 0, 0),
TraversalResult {
inscription_number: OrdinalInscriptionNumber {
classic: if cursed { -1 } else { 0 },
jubilee: 0,
},
inscription_input_index: 0,
transaction_identifier_inscription: tx_id,
ordinal_number,
transfers: 0,
},
);
let mut pg_client = pg_test_connection().await;
ordinals_pg::migrate(&mut pg_client).await?;
let result = {
let mut ord_client = pg_pool_client(&pg_test_connection_pool()).await?;
let client = pg_begin(&mut ord_client).await?;
let mut block = TestBlockBuilder::new()
.height(block_height)
// Coinbase
.add_transaction(TestTransactionBuilder::new().build())
.add_transaction(
TestTransactionBuilder::new()
.hash(
"b4722ad74e7092a194e367f2ec0609994ef7a006db4f9b9d055b46cfb6514e06"
.into(),
)
.add_input(TxIn {
previous_output: OutPoint {
txid: TransactionIdentifier { hash: "f181aa98f2572879bd02278c72c83c7eaac2db82af713d1d239fc41859b2a26e".into() },
vout: 0,
value: 10000,
block_height: 884200,
},
script_sig: "0x00".into(),
sequence: 0,
witness: vec!["0x00".into()],
})
.add_output(TxOut { value: 8000, script_pubkey })
.add_ordinal_operation(OrdinalOperation::InscriptionRevealed(
OrdinalInscriptionRevealData {
content_bytes: "0x101010".into(),
content_type: "text/plain".into(),
content_length: 3,
inscription_number: OrdinalInscriptionNumber {
classic: if cursed { -1 } else { 0 },
jubilee: 0,
},
inscription_fee: 0,
inscription_output_value: 0,
inscription_id: "".into(),
inscription_input_index: 0,
inscription_pointer: Some(0),
inscriber_address: Some("bc1pd99n363yjz8gd2zhy7gstsmk4qkdz4t029j44wewhmee3dta429sm5xqrd".into()),
delegate: None,
metaprotocol: None,
metadata: None,
parents: vec![],
ordinal_number: 0,
ordinal_block_height: 0,
ordinal_offset: 0,
tx_index: 0,
transfers_pre_inscription: 0,
satpoint_post_inscription: "".into(),
curse_type: if cursed { Some(OrdinalInscriptionCurseType::Generic) } else { None },
charms: 0,
},
))
.build(),
)
.build();
update_block_inscriptions_with_consensus_sequence_data(
&mut block,
&mut sequence_cursor,
&mut cache_l1,
&client,
&ctx,
)
.await?;
let result = &block.transactions[1].metadata.ordinal_operations[0];
// println!("{:?}", result);
let charms = match result {
OrdinalOperation::InscriptionRevealed(data) => data.charms,
_ => unreachable!(),
};
// println!("{:?}", Charm::charms(charms));
Ok(Charm::charms(charms))
};
pg_reset_db(&mut pg_client).await?;
result
}
}

View File

@@ -1,5 +1,8 @@
use chainhook_types::{
bitcoin::{OutPoint, TxIn, TxOut}, BitcoinBlockData, BitcoinBlockMetadata, BitcoinNetwork, BitcoinTransactionData, BitcoinTransactionMetadata, BlockIdentifier, Brc20Operation, OrdinalInscriptionCharms, OrdinalInscriptionNumber, OrdinalInscriptionRevealData, OrdinalOperation, TransactionIdentifier
bitcoin::{OutPoint, TxIn, TxOut},
BitcoinBlockData, BitcoinBlockMetadata, BitcoinNetwork, BitcoinTransactionData,
BitcoinTransactionMetadata, BlockIdentifier, Brc20Operation, OrdinalInscriptionNumber,
OrdinalInscriptionRevealData, OrdinalOperation, TransactionIdentifier,
};
pub struct TestBlockBuilder {
@@ -101,7 +104,7 @@ impl TestTransactionBuilder {
transfers_pre_inscription: 0,
satpoint_post_inscription: "b61b0172d95e266c18aea0c624db987e971a5d6d4ebc2aaed85da4642d635735:0:0".to_string(),
curse_type: None,
charms: OrdinalInscriptionCharms::none(),
charms: 0,
},
)];
tx

View File

@@ -32,6 +32,7 @@ pub struct DbInscription {
pub metaprotocol: Option<String>,
pub delegate: Option<String>,
pub timestamp: PgBigIntU32,
pub charms: PgBigIntU32,
}
impl DbInscription {
@@ -82,6 +83,7 @@ impl DbInscription {
metaprotocol: reveal.metaprotocol.clone(),
delegate: reveal.delegate.clone(),
timestamp: PgBigIntU32(timestamp),
charms: PgBigIntU32(reveal.charms as u32),
}
}
}
@@ -111,6 +113,7 @@ impl FromPgRow for DbInscription {
metaprotocol: row.get("metaprotocol"),
delegate: row.get("delegate"),
timestamp: row.get("timestamp"),
charms: row.get("charms"),
}
}
}

View File

@@ -33,7 +33,7 @@ impl DbInscriptionRecursion {
#[cfg(test)]
mod test {
use chainhook_types::{OrdinalInscriptionCharms, OrdinalInscriptionNumber, OrdinalInscriptionRevealData};
use chainhook_types::{OrdinalInscriptionNumber, OrdinalInscriptionRevealData};
use super::DbInscriptionRecursion;
@@ -61,7 +61,7 @@ mod test {
transfers_pre_inscription: 0,
satpoint_post_inscription: "e47a70a218dfa746ba410b1c057403bb481523d830562fd8dec61ec4d2915e5f:0:0".to_string(),
curse_type: None,
charms: OrdinalInscriptionCharms::none(),
charms: 0,
};
let recursions = DbInscriptionRecursion::from_reveal(&reveal).unwrap();
assert_eq!(2, recursions.len());

View File

@@ -260,15 +260,16 @@ async fn insert_inscriptions<T: GenericClient>(
params.push(&row.metaprotocol);
params.push(&row.delegate);
params.push(&row.timestamp);
params.push(&row.charms);
}
client
.query(
&format!("INSERT INTO inscriptions
(inscription_id, ordinal_number, number, classic_number, block_height, block_hash, tx_id, tx_index, address,
mime_type, content_type, content_length, content, fee, curse_type, recursive, input_index, pointer, metadata,
metaprotocol, delegate, timestamp)
metaprotocol, delegate, timestamp, charms)
VALUES {}
ON CONFLICT (number) DO NOTHING", utils::multi_row_query_param_str(chunk.len(), 22)),
ON CONFLICT (number) DO NOTHING", utils::multi_row_query_param_str(chunk.len(), 23)),
&params,
)
.await
@@ -1010,7 +1011,8 @@ mod test {
FromPgRow,
};
use chainhook_types::{
OrdinalInscriptionCharms, OrdinalInscriptionNumber, OrdinalInscriptionRevealData, OrdinalInscriptionTransferData, OrdinalInscriptionTransferDestination, OrdinalOperation
OrdinalInscriptionNumber, OrdinalInscriptionRevealData, OrdinalInscriptionTransferData,
OrdinalInscriptionTransferDestination, OrdinalOperation,
};
use deadpool_postgres::GenericClient;
@@ -1203,7 +1205,7 @@ mod test {
transfers_pre_inscription: 0,
satpoint_post_inscription: "b61b0172d95e266c18aea0c624db987e971a5d6d4ebc2aaed85da4642d635735:0:0".to_string(),
curse_type: None,
charms: OrdinalInscriptionCharms::none(),
charms: 0,
},
))
.build()

View File

@@ -0,0 +1 @@
ALTER TABLE inscriptions ADD COLUMN charms BIGINT NOT NULL DEFAULT 0;