Skip to content

Commit ecd3c7b

Browse files
authored
Merge pull request #52 from me-rob/rwei/utxo-based-spent-outputs
expand spent outputs to utxos
2 parents d5da162 + 71cf6cf commit ecd3c7b

File tree

4 files changed

+43
-15
lines changed

4 files changed

+43
-15
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@magiceden-oss/runestone-lib",
3-
"version": "0.9.6-alpha",
3+
"version": "0.9.7-alpha",
44
"description": "",
55
"main": "./dist/index.js",
66
"types": "./dist/index.d.ts",

src/indexer/types.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,7 @@ export namespace RuneLocation {
104104
}
105105
}
106106

107-
export type RuneOutput = {
108-
txid: string;
109-
vout: number;
110-
};
107+
export type SpentRuneUtxoBalance = RuneUtxoBalance & { mempoolTxid: string };
111108

112109
export type RuneUtxoBalance = {
113110
txid: string;
@@ -156,6 +153,6 @@ export type RuneBlockIndex = {
156153
etchings: RuneEtching[];
157154
mintCounts: RuneMintCount[];
158155
utxoBalances: RuneUtxoBalance[];
159-
spentOutputs: RuneOutput[];
156+
spentBalances: SpentRuneUtxoBalance[];
160157
burnedBalances: RuneBalance[];
161158
};

src/indexer/updater.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,18 @@ import { BitcoinRpcClient } from '../rpcclient';
1212
import { Rune } from '../rune';
1313
import { Runestone } from '../runestone';
1414
import { script } from '../script';
15+
import { SpacedRune } from '../spacedrune';
1516
import {
1617
BlockInfo,
17-
RuneBlockIndex,
1818
RuneBalance,
19+
RuneBlockIndex,
1920
RuneEtching,
2021
RuneLocation,
2122
RuneMintCount,
22-
RuneOutput,
2323
RuneUtxoBalance,
2424
RunestoneStorage,
25+
SpentRuneUtxoBalance,
2526
} from './types';
26-
import { SpacedRune } from '../spacedrune';
2727

2828
function isScriptPubKeyHexOpReturn(scriptPubKeyHex: string) {
2929
return scriptPubKeyHex && Buffer.from(scriptPubKeyHex, 'hex')[0] === OP_RETURN;
@@ -39,7 +39,7 @@ export class RuneUpdater implements RuneBlockIndex {
3939
block: BlockInfo;
4040
etchings: RuneEtching[] = [];
4141
utxoBalances: RuneUtxoBalance[] = [];
42-
spentOutputs: RuneOutput[] = [];
42+
spentBalances: SpentRuneUtxoBalance[] = [];
4343

4444
private _minimum: Rune;
4545
private _mintCountsByRuneLocation: Map<string, RuneMintCount> = new Map();
@@ -446,13 +446,22 @@ export class RuneUpdater implements RuneBlockIndex {
446446
const utxoBalance =
447447
utxoBalancesByOutputLocation.get(`${input.txid}:${input.vout}`) ??
448448
(await this._storage.getUtxoBalance(input.txid, input.vout));
449-
this.spentOutputs.push({ txid: input.txid, vout: input.vout });
450449
for (const additionalBalance of utxoBalance) {
451450
const runeId = additionalBalance.runeId;
452451
const runeLocation = RuneLocation.toString(runeId);
453452
const balance = unallocated.get(runeLocation) ?? { runeId, amount: 0n };
454453
unallocated.set(runeLocation, balance);
455454
balance.amount = u128.checkedAddThrow(u128(balance.amount), u128(additionalBalance.amount));
455+
this.spentBalances.push({
456+
txid: input.txid,
457+
vout: input.vout,
458+
address: additionalBalance.address,
459+
scriptPubKey: additionalBalance.scriptPubKey,
460+
runeId: additionalBalance.runeId,
461+
runeTicker: additionalBalance.runeTicker,
462+
amount: additionalBalance.amount,
463+
mempoolTxid: tx.txid,
464+
});
456465
}
457466
}
458467

test/updater.test.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,7 @@ describe('edict', () => {
882882
await runeUpdater.indexRunes(tx2, 89);
883883
expect(runeUpdater.etchings.length).toBe(0);
884884
expect(runeUpdater.utxoBalances.length).toBe(2);
885+
expect(runeUpdater.spentBalances.length).toBe(2);
885886
expect(runeUpdater.utxoBalances[0]).toMatchObject({
886887
txid: 'txid',
887888
vout: 1,
@@ -902,10 +903,31 @@ describe('edict', () => {
902903
},
903904
amount: 400n,
904905
});
905-
expect(runeUpdater.spentOutputs).toEqual([
906-
{ txid: 'parenttxid', vout: 0 },
907-
{ txid: 'txid', vout: 1 },
908-
]);
906+
expect(runeUpdater.spentBalances[0]).toMatchObject({
907+
txid: 'parenttxid',
908+
vout: 0,
909+
address: '3P4WqXDbSLRhzo2H6MT6YFbvBKBDPLbVtQ',
910+
scriptPubKey: Buffer.from('a914ea6b832a05c6ca578baa3836f3f25553d41068a587', 'hex'),
911+
runeId: {
912+
block: 888,
913+
tx: 8,
914+
},
915+
runeTicker: 'TESTRUNE',
916+
amount: 400n,
917+
mempoolTxid: 'txid',
918+
});
919+
expect(runeUpdater.spentBalances[1]).toMatchObject({
920+
txid: 'txid',
921+
vout: 1,
922+
address: '3P4WqXDbSLRhzo2H6MT6YFbvBKBDPLbVtQ',
923+
runeId: {
924+
block: 888,
925+
tx: 8,
926+
},
927+
runeTicker: 'TESTRUNE',
928+
amount: 400n,
929+
mempoolTxid: 'childtxid',
930+
});
909931
});
910932

911933
test('edict with invalid output is cenotaph', async () => {

0 commit comments

Comments
 (0)