Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.

Commit df46fcc

Browse files
fix: make getInscriptions to return txid and vout object (#15)
* fix: make getInscriptions to return txid and vout object
1 parent 3014c7e commit df46fcc

File tree

11 files changed

+151
-66
lines changed

11 files changed

+151
-66
lines changed

docs/WalletIntegration.md

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,11 @@ export interface UTXO {
5656
scriptPubKey: string;
5757
}
5858

59-
export interface Inscription {
60-
// output of the inscription in the format of `txid:vout`
61-
output: string;
59+
export interface InscriptionIdentifier {
60+
// hash of transaction that holds the ordinals/brc-2-/runes etc in the UTXO
61+
txid: string;
62+
// index of the output in the transaction
63+
vout: number;
6264
}
6365

6466
// supported networks
@@ -342,25 +344,47 @@ export class OKXWallet extends WalletProvider {
342344
return await getTipHeight();
343345
};
344346

345-
// Inscriptions(Ordinal/Runes/BRC-20 etc)
346-
getInscriptions = async (): Promise<Inscription[]> => {
347+
getInscriptions = async (): Promise<InscriptionIdentifier[]> => {
347348
if (!this.okxWalletInfo) {
348349
throw new Error("OKX Wallet not connected");
349350
}
350-
const inscriptions: Inscription[] = [];
351+
// max num of iterations to prevent infinite loop
352+
const MAX_ITERATIONS = 100;
353+
// Fetch inscriptions in batches of 100
354+
const limit = 100;
355+
const inscriptionIdentifiers: InscriptionIdentifier[] = [];
351356
let cursor = 0;
352-
while (true) {
353-
const { list } = await this.bitcoinNetworkProvider.getInscriptions(
354-
cursor,
355-
DEFAULT_INSCRIPTION_LIMIT,
356-
);
357-
inscriptions.push(...list);
358-
if (list.length < DEFAULT_INSCRIPTION_LIMIT) {
359-
break;
357+
let iterations = 0;
358+
try {
359+
while (iterations < MAX_ITERATIONS) {
360+
const { list } = await this.bitcoinNetworkProvider.getInscriptions(
361+
cursor,
362+
limit,
363+
);
364+
const identifiers = list.map((i: { output: string }) => {
365+
const [txid, vout] = i.output.split(":");
366+
return {
367+
txid,
368+
vout,
369+
};
370+
});
371+
inscriptionIdentifiers.push(...identifiers);
372+
if (list.length < limit) {
373+
break;
374+
}
375+
cursor += limit;
376+
iterations++;
377+
if (iterations >= MAX_ITERATIONS) {
378+
throw new Error(
379+
"Exceeded maximum iterations when fetching inscriptions",
380+
);
381+
}
360382
}
361-
cursor += DEFAULT_INSCRIPTION_LIMIT;
383+
} catch (error) {
384+
throw new Error("Failed to get inscriptions from OKX Wallet");
362385
}
363-
return inscriptions;
386+
387+
return inscriptionIdentifiers;
364388
};
365389
}
366390
```

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "simple-staking",
3-
"version": "0.2.20",
3+
"version": "0.2.21",
44
"private": true,
55
"scripts": {
66
"dev": "next dev",

src/utils/utxo/index.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { postVerifyUtxoOrdinals, UtxoInfo } from "@/app/api/postFilterOrdinals";
22

3-
import { Inscription, UTXO } from "../wallet/wallet_provider";
3+
import { InscriptionIdentifier, UTXO } from "../wallet/wallet_provider";
44

55
/**
66
* Filters out UTXOs that contain ordinals.
@@ -17,19 +17,25 @@ import { Inscription, UTXO } from "../wallet/wallet_provider";
1717
export const filterOrdinals = async (
1818
utxos: UTXO[],
1919
address: string,
20-
getInscriptionsFromWalletCb: () => Promise<Inscription[]>,
20+
getInscriptionsFromWalletCb?: () => Promise<InscriptionIdentifier[]>,
2121
): Promise<UTXO[]> => {
2222
if (!utxos.length) {
2323
return [];
2424
}
25+
// fallback to Babylon API if the wallet does not support getting inscriptions
26+
if (!getInscriptionsFromWalletCb) {
27+
return filterFromApi(utxos, address);
28+
}
2529
// try to get the ordinals from the wallet first, if the wallet supports it
2630
// otherwise fallback to the Babylon API
2731
try {
2832
const inscriptions = await getInscriptionsFromWalletCb();
2933
// filter out the utxos that contains ordinals
3034
return utxos.filter(
3135
(utxo) =>
32-
!inscriptions.find((i) => i.output === `${utxo.txid}:${utxo.vout}`),
36+
!inscriptions.find((i) => {
37+
return i.txid === utxo.txid && i.vout === utxo.vout;
38+
}),
3339
);
3440
} catch (error) {
3541
return filterFromApi(utxos, address);

src/utils/wallet/providers/bitget_wallet.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from "../../mempool_api";
1212
import {
1313
Fees,
14-
Inscription,
14+
InscriptionIdentifier,
1515
Network,
1616
UTXO,
1717
WalletProvider,
@@ -210,7 +210,7 @@ export class BitgetWallet extends WalletProvider {
210210
return await getTipHeight();
211211
};
212212

213-
getInscriptions(): Promise<Inscription[]> {
213+
getInscriptions(): Promise<InscriptionIdentifier[]> {
214214
throw new Error("Method not implemented.");
215215
}
216216
}

src/utils/wallet/providers/keystone/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import {
3232
import { WalletError, WalletErrorType } from "../../errors";
3333
import {
3434
Fees,
35-
Inscription,
35+
InscriptionIdentifier,
3636
Network,
3737
UTXO,
3838
WalletProvider,
@@ -292,7 +292,7 @@ export class KeystoneWallet extends WalletProvider {
292292
return await getTipHeight();
293293
};
294294

295-
getInscriptions(): Promise<Inscription[]> {
295+
getInscriptions(): Promise<InscriptionIdentifier[]> {
296296
throw new Error("Method not implemented.");
297297
}
298298
}

src/utils/wallet/providers/okx_wallet.ts

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ import {
1212
pushTx,
1313
} from "../../mempool_api";
1414
import {
15-
DEFAULT_INSCRIPTION_LIMIT,
1615
Fees,
17-
Inscription,
16+
InscriptionIdentifier,
1817
Network,
1918
UTXO,
2019
WalletInfo,
@@ -176,23 +175,51 @@ export class OKXWallet extends WalletProvider {
176175
};
177176

178177
// Inscriptions are only available on OKX Wallet BTC mainnet (i.e okxWallet.bitcoin)
179-
getInscriptions = async (): Promise<Inscription[]> => {
178+
getInscriptions = async (): Promise<InscriptionIdentifier[]> => {
180179
if (!this.okxWalletInfo) {
181180
throw new Error("OKX Wallet not connected");
182181
}
183-
const inscriptions: Inscription[] = [];
184-
let cursor = 0;
185-
while (true) {
186-
const { list } = await this.bitcoinNetworkProvider.getInscriptions(
187-
cursor,
188-
DEFAULT_INSCRIPTION_LIMIT,
182+
if (this.networkEnv !== Network.MAINNET) {
183+
throw new Error(
184+
"Inscriptions are only available on OKX Wallet BTC mainnet",
189185
);
190-
inscriptions.push(...list);
191-
if (list.length < DEFAULT_INSCRIPTION_LIMIT) {
192-
break;
186+
}
187+
// max num of iterations to prevent infinite loop
188+
const MAX_ITERATIONS = 100;
189+
// Fetch inscriptions in batches of 100
190+
const limit = 100;
191+
const inscriptionIdentifiers: InscriptionIdentifier[] = [];
192+
let cursor = 0;
193+
let iterations = 0;
194+
try {
195+
while (iterations < MAX_ITERATIONS) {
196+
const { list } = await this.bitcoinNetworkProvider.getInscriptions(
197+
cursor,
198+
limit,
199+
);
200+
const identifiers = list.map((i: { output: string }) => {
201+
const [txid, vout] = i.output.split(":");
202+
return {
203+
txid,
204+
vout,
205+
};
206+
});
207+
inscriptionIdentifiers.push(...identifiers);
208+
if (list.length < limit) {
209+
break;
210+
}
211+
cursor += limit;
212+
iterations++;
213+
if (iterations >= MAX_ITERATIONS) {
214+
throw new Error(
215+
"Exceeded maximum iterations when fetching inscriptions",
216+
);
217+
}
193218
}
194-
cursor += DEFAULT_INSCRIPTION_LIMIT;
219+
} catch (error) {
220+
throw new Error("Failed to get inscriptions from OKX Wallet");
195221
}
196-
return inscriptions;
222+
223+
return inscriptionIdentifiers;
197224
};
198225
}

src/utils/wallet/providers/onekey_wallet.ts

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ import {
77
pushTx,
88
} from "../../mempool_api";
99
import {
10-
DEFAULT_INSCRIPTION_LIMIT,
1110
Fees,
12-
Inscription,
11+
InscriptionIdentifier,
1312
Network,
1413
UTXO,
1514
WalletInfo,
@@ -165,20 +164,46 @@ export class OneKeyWallet extends WalletProvider {
165164
}
166165

167166
// Inscriptions are only available on oneKey Wallet BTC mainnet
168-
getInscriptions = async (): Promise<Inscription[]> => {
169-
const inscriptions: Inscription[] = [];
167+
getInscriptions = async (): Promise<InscriptionIdentifier[]> => {
168+
if (this.networkEnv !== Network.MAINNET) {
169+
throw new Error("Inscriptions are only available on OneKey mainnet");
170+
}
171+
// max num of iterations to prevent infinite loop
172+
const MAX_ITERATIONS = 100;
173+
// Fetch inscriptions in batches of 100
174+
const limit = 100;
175+
const inscriptionIdentifiers: InscriptionIdentifier[] = [];
170176
let cursor = 0;
171-
while (true) {
172-
const { list } = await this.bitcoinNetworkProvider.getInscriptions(
173-
cursor,
174-
DEFAULT_INSCRIPTION_LIMIT,
175-
);
176-
inscriptions.push(...list);
177-
if (list.length < DEFAULT_INSCRIPTION_LIMIT) {
178-
break;
177+
let iterations = 0;
178+
try {
179+
while (iterations < MAX_ITERATIONS) {
180+
const { list } = await this.bitcoinNetworkProvider.getInscriptions(
181+
cursor,
182+
limit,
183+
);
184+
const identifiers = list.map((i: { output: string }) => {
185+
const [txid, vout] = i.output.split(":");
186+
return {
187+
txid,
188+
vout,
189+
};
190+
});
191+
inscriptionIdentifiers.push(...identifiers);
192+
if (list.length < limit) {
193+
break;
194+
}
195+
cursor += limit;
196+
iterations++;
197+
if (iterations >= MAX_ITERATIONS) {
198+
throw new Error(
199+
"Exceeded maximum iterations when fetching inscriptions",
200+
);
201+
}
179202
}
180-
cursor += DEFAULT_INSCRIPTION_LIMIT;
203+
} catch (error) {
204+
throw new Error("Failed to get inscriptions from OKX Wallet");
181205
}
182-
return inscriptions;
206+
207+
return inscriptionIdentifiers;
183208
};
184209
}

src/utils/wallet/providers/tomo_wallet.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99

1010
import {
1111
Fees,
12-
Inscription,
12+
InscriptionIdentifier,
1313
Network,
1414
UTXO,
1515
WalletInfo,
@@ -171,7 +171,7 @@ export class TomoWallet extends WalletProvider {
171171
return await getTipHeight();
172172
};
173173

174-
getInscriptions(): Promise<Inscription[]> {
174+
getInscriptions(): Promise<InscriptionIdentifier[]> {
175175
throw new Error("Method not implemented.");
176176
}
177177
}

src/utils/wallet/wallet_provider.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ export interface UTXO {
2323
scriptPubKey: string;
2424
}
2525

26-
export interface Inscription {
27-
// output of the inscription in the format of `txid:vout`
28-
output: string;
26+
export interface InscriptionIdentifier {
27+
// hash of transaction that holds the ordinals/brc-2-/runes etc in the UTXO
28+
txid: string;
29+
// index of the output in the transaction
30+
vout: number;
2931
}
30-
3132
// supported networks
3233
export enum Network {
3334
MAINNET = "mainnet",
@@ -41,9 +42,6 @@ export type WalletInfo = {
4142
address: string;
4243
};
4344

44-
// Default number of inscriptions to fetch in a single method call
45-
export const DEFAULT_INSCRIPTION_LIMIT = 100;
46-
4745
/**
4846
* Abstract class representing a wallet provider.
4947
* Provides methods for connecting to a wallet, retrieving wallet information, signing transactions, and more.
@@ -153,5 +151,5 @@ export abstract class WalletProvider {
153151
* Retrieves the inscriptions for the connected wallet.
154152
* @returns A promise that resolves to an array of inscriptions.
155153
*/
156-
abstract getInscriptions(): Promise<Inscription[]>;
154+
abstract getInscriptions(): Promise<InscriptionIdentifier[]>;
157155
}

0 commit comments

Comments
 (0)