Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions apps/api/migrations/0040_nullable_order_expire_index.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
-- Counterparty Core now returns open orders that never expire: expiration = 0
-- and expire_index = NULL. 0022 declared expire_index NOT NULL, so one such
-- order failed its market's whole write batch and left that book stale.
--
-- NULL now means "no expiry". SQLite cannot drop a NOT NULL constraint with
-- ALTER TABLE, so the table is rebuilt: identical to 0022 except for that one
-- column, every row copied as it is, and both of 0022's indexes recreated. No
-- table references orders and no trigger is defined on it, so nothing else
-- has to be carried across.

DROP TABLE IF EXISTS orders_new;

CREATE TABLE orders_new (
tx_hash TEXT PRIMARY KEY,
tx_index INTEGER NOT NULL,
block_index INTEGER NOT NULL,
source TEXT NOT NULL,
asset TEXT NOT NULL,
side TEXT NOT NULL,
token_quantity TEXT NOT NULL,
xcp_quantity TEXT NOT NULL,
-- NULL: the order never expires (Core's expiration = 0).
expire_index INTEGER,
token_remaining TEXT NOT NULL,
xcp_remaining TEXT NOT NULL,
status TEXT NOT NULL,
updated_at INTEGER NOT NULL
);

INSERT INTO orders_new
(tx_hash, tx_index, block_index, source, asset, side,
token_quantity, xcp_quantity, expire_index,
token_remaining, xcp_remaining, status, updated_at)
SELECT tx_hash, tx_index, block_index, source, asset, side,
token_quantity, xcp_quantity, expire_index,
token_remaining, xcp_remaining, status, updated_at
FROM orders;

DROP TABLE orders;

ALTER TABLE orders_new RENAME TO orders;

-- Dropped with the old table; recreated exactly as 0022 defined them.
CREATE INDEX idx_orders_recent ON orders(block_index DESC, tx_index DESC);

CREATE INDEX idx_orders_open ON orders(block_index DESC, tx_index DESC)
WHERE status = 'open';
19 changes: 17 additions & 2 deletions apps/api/src/indexer/orders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ interface OrderRow {
tokenRemaining: string;
xcpRemaining: string;
status: string;
expireIndex: number;
/** Null for an order that never expires. */
expireIndex: number | null;
}

/**
Expand Down Expand Up @@ -97,12 +98,26 @@ function toRows(asset: string, orders: CpOrder[]): OrderRow[] {
tokenRemaining: String(buying ? o.get_remaining : o.give_remaining),
xcpRemaining: String(buying ? o.give_remaining : o.get_remaining),
status: o.status,
expireIndex: o.expire_index,
expireIndex: expireIndex(o),
});
}
return rows;
}

/**
* The block an order expires at, or null when it never does.
*
* Core returns expiration = 0 with expire_index = null for an order that never
* expires. Should it ever omit expire_index for one that does expire, the
* block is still derivable from where the order was placed and how long it
* asked to stay open.
*/
function expireIndex(o: CpOrder): number | null {
if (typeof o.expire_index === "number" && Number.isFinite(o.expire_index)) return o.expire_index;
if (typeof o.expiration === "number" && o.expiration > 0) return o.block_index + o.expiration;
return null;
}

/**
* A fingerprint of everything about this market's book that can change.
*
Expand Down
5 changes: 4 additions & 1 deletion apps/api/src/integrations/counterparty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,10 @@ export interface CpOrder {
get_asset: string;
get_quantity: number | string;
get_remaining: number | string;
expire_index: number;
/** Blocks the order stays open for; 0 means it never expires. */
expiration: number;
/** The block it expires at, or null for an order that never expires. */
expire_index: number | null;
/** `open`, `filled`, `cancelled` or `expired`. Counterparty has no
* "partially filled" status — that is an open order whose remaining is
* below its original, and the tape derives it. */
Expand Down
3 changes: 2 additions & 1 deletion apps/api/src/queries/activity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ export interface OrderRow {
token_remaining: string;
xcp_remaining: string;
status: string;
expire_index: number;
/** Null for an order that never expires. */
expire_index: number | null;
divisible: number;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1070,7 +1070,7 @@ export function ActivityTabs({
) : (
<>
{num.percent(filled, { digits: 0 })} ·{" "}
{o!.expire_index === null ? "GTC" : num.commas(o!.expire_index)}
{o!.expire_index === null ? t("No expiry") : num.commas(o!.expire_index)}
</>
)}
</td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -522,9 +522,11 @@ function OrderTape({ rows, height }: { rows: ActivityOrder[]; height?: number })
{r.state === "partial"
? t("{pct}% filled", { pct })
: r.state === "open"
? height
? t("{eta} left", { eta: blocksEta(r.expireBlock - height, t) })
: ""
? r.expireBlock === null
? t("No expiry")
: height
? t("{eta} left", { eta: blocksEta(r.expireBlock - height, t) })
: ""
: r.state === "filled"
? ""
: pct > 0
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/app/[lang]/profile/_components/orders-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export function OrdersTab({
)}
<span className="ml-2 text-xs text-gray-500 dark:text-gray-400">
{t("{pct}% filled", { pct: (filled * 100).toFixed(0) })} ·{" "}
{o.expire_index === null ? "GTC" : t("expires block {n}", { n: num.commas(o.expire_index) })}
{o.expire_index === null ? t("No expiry") : t("expires block {n}", { n: num.commas(o.expire_index) })}
</span>
</div>
{canCancel && (
Expand Down
7 changes: 4 additions & 3 deletions apps/web/src/lib/api/launchpad-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1511,7 +1511,8 @@ export interface ActivityOrder {
side: "buy" | "sell";
state: OrderState;
block: number;
expireBlock: number;
/** Null for an order that never expires. */
expireBlock: number | null;
/** Original size; the order's price is a statement about these. */
tokenQuantity: Raw;
xcpQuantity: Raw;
Expand Down Expand Up @@ -1705,7 +1706,7 @@ interface ApiActivityOrder {
side: string;
state: string;
block_index: number;
expire_index: number;
expire_index: number | null;
token_quantity: Raw;
xcp_quantity: Raw;
token_remaining: Raw;
Expand Down Expand Up @@ -1777,7 +1778,7 @@ export async function fetchActivityOrders(
// undefined.
state: ORDER_STATES.find((s) => s === r.state) ?? "open",
block: r.block_index,
expireBlock: r.expire_index,
expireBlock: typeof r.expire_index === "number" ? r.expire_index : null,
tokenQuantity: r.token_quantity,
xcpQuantity: r.xcp_quantity,
tokenRemaining: r.token_remaining,
Expand Down
5 changes: 5 additions & 0 deletions apps/web/src/locales/_source.json
Original file line number Diff line number Diff line change
Expand Up @@ -2537,6 +2537,11 @@
"No closed positions yet.": [
"app/[lang]/profile/_components/history-tab.tsx"
],
"No expiry": [
"app/[lang]/[asset]/_components/activity-tabs.tsx",
"app/[lang]/activity/_components/activity-view.tsx",
"app/[lang]/profile/_components/orders-tab.tsx"
],
"no history": [
"app/[lang]/[asset]/_components/activity-tabs.tsx"
],
Expand Down
3 changes: 2 additions & 1 deletion apps/web/src/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -1293,5 +1293,6 @@
"If it fails, every minter’s XCP is automatically refunded.": "Si no se completa, se devuelve automáticamente todo el XCP de cada participante.",
"Finish launching {asset}": "Terminar de lanzar {asset}",
"The inscription commit for {asset} is broadcast, but its reveal is not. The launch exists only once the reveal is on-chain, and until then the commit's BTC waits in an output only that reveal can spend.": "El commit de la inscripción de {asset} está transmitido, pero su reveal no. El lanzamiento solo existe cuando el reveal está en la cadena, y hasta entonces el BTC del commit espera en una salida que solo ese reveal puede gastar.",
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.": "El commit de la inscripción de {asset} nunca llegó a la cadena, y una de las monedas que gasta ya la gastó otra transacción confirmada, así que nunca llegará. Nada de su BTC espera un reveal, y puedes empezar un lanzamiento nuevo."
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.": "El commit de la inscripción de {asset} nunca llegó a la cadena, y una de las monedas que gasta ya la gastó otra transacción confirmada, así que nunca llegará. Nada de su BTC espera un reveal, y puedes empezar un lanzamiento nuevo.",
"No expiry": "Sin vencimiento"
}
3 changes: 2 additions & 1 deletion apps/web/src/locales/es.status.json
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,7 @@
"If it fails, every minter’s XCP is automatically refunded.",
"Finish launching {asset}",
"The inscription commit for {asset} is broadcast, but its reveal is not. The launch exists only once the reveal is on-chain, and until then the commit's BTC waits in an output only that reveal can spend.",
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch."
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.",
"No expiry"
]
}
3 changes: 2 additions & 1 deletion apps/web/src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1293,5 +1293,6 @@
"If it fails, every minter’s XCP is automatically refunded.": "En cas d’échec, la totalité des XCP de chaque participant est automatiquement remboursée.",
"Finish launching {asset}": "Terminer le lancement de {asset}",
"The inscription commit for {asset} is broadcast, but its reveal is not. The launch exists only once the reveal is on-chain, and until then the commit's BTC waits in an output only that reveal can spend.": "Le commit de l'inscription de {asset} est diffusé, mais pas son reveal. Le lancement n'existe qu'une fois le reveal on-chain ; d'ici là, les BTC du commit attendent dans une sortie que seul ce reveal peut dépenser.",
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.": "Le commit de l'inscription de {asset} n'est jamais arrivé on-chain, et une des pièces qu'il dépense a depuis été dépensée par une autre transaction confirmée : il n'y arrivera donc jamais. Aucun de ses BTC n'attend de reveal, et vous pouvez commencer un nouveau lancement."
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.": "Le commit de l'inscription de {asset} n'est jamais arrivé on-chain, et une des pièces qu'il dépense a depuis été dépensée par une autre transaction confirmée : il n'y arrivera donc jamais. Aucun de ses BTC n'attend de reveal, et vous pouvez commencer un nouveau lancement.",
"No expiry": "Sans expiration"
}
3 changes: 2 additions & 1 deletion apps/web/src/locales/fr.status.json
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,7 @@
"If it fails, every minter’s XCP is automatically refunded.",
"Finish launching {asset}",
"The inscription commit for {asset} is broadcast, but its reveal is not. The launch exists only once the reveal is on-chain, and until then the commit's BTC waits in an output only that reveal can spend.",
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch."
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.",
"No expiry"
]
}
3 changes: 2 additions & 1 deletion apps/web/src/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -1293,5 +1293,6 @@
"If it fails, every minter’s XCP is automatically refunded.": "成立しなかった場合、すべての参加者に拠出したXCPが自動的に全額返還されます。",
"Finish launching {asset}": "{asset} のローンチを完了",
"The inscription commit for {asset} is broadcast, but its reveal is not. The launch exists only once the reveal is on-chain, and until then the commit's BTC waits in an output only that reveal can spend.": "{asset} の刻印のコミットはブロードキャスト済みですが、リビールはまだです。ローンチはリビールがオンチェーンになって初めて成立し、それまでコミットの BTC は、そのリビールだけが使える出力で待機します。",
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.": "{asset} の刻印のコミットはオンチェーンに届かず、それが使うコインの一つはその後、別の承認済みトランザクションで使われたため、今後も届くことはありません。リビールを待っている BTC はなく、新しいローンチを始められます。"
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.": "{asset} の刻印のコミットはオンチェーンに届かず、それが使うコインの一つはその後、別の承認済みトランザクションで使われたため、今後も届くことはありません。リビールを待っている BTC はなく、新しいローンチを始められます。",
"No expiry": "有効期限なし"
}
3 changes: 2 additions & 1 deletion apps/web/src/locales/ja.status.json
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,7 @@
"If it fails, every minter’s XCP is automatically refunded.",
"Finish launching {asset}",
"The inscription commit for {asset} is broadcast, but its reveal is not. The launch exists only once the reveal is on-chain, and until then the commit's BTC waits in an output only that reveal can spend.",
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch."
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.",
"No expiry"
]
}
3 changes: 2 additions & 1 deletion apps/web/src/locales/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -1293,5 +1293,6 @@
"If it fails, every minter’s XCP is automatically refunded.": "출시가 실패하면 모든 민팅 참여자가 지불한 XCP 전액이 자동으로 환불됩니다.",
"Finish launching {asset}": "{asset} 런칭 마치기",
"The inscription commit for {asset} is broadcast, but its reveal is not. The launch exists only once the reveal is on-chain, and until then the commit's BTC waits in an output only that reveal can spend.": "{asset} 인스크립션의 커밋은 전송되었지만 리빌은 아직입니다. 런칭은 리빌이 온체인에 올라가야 성립하며, 그때까지 커밋의 BTC는 그 리빌만 사용할 수 있는 출력에 머뭅니다.",
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.": "{asset} 인스크립션의 커밋은 온체인에 올라가지 못했고, 커밋이 사용하는 코인 하나가 이후 다른 확정된 트랜잭션에서 사용되어 앞으로도 올라갈 수 없습니다. 리빌을 기다리는 BTC는 없으며, 새 런칭을 시작할 수 있습니다."
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.": "{asset} 인스크립션의 커밋은 온체인에 올라가지 못했고, 커밋이 사용하는 코인 하나가 이후 다른 확정된 트랜잭션에서 사용되어 앞으로도 올라갈 수 없습니다. 리빌을 기다리는 BTC는 없으며, 새 런칭을 시작할 수 있습니다.",
"No expiry": "만료 없음"
}
3 changes: 2 additions & 1 deletion apps/web/src/locales/ko.status.json
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,7 @@
"If it fails, every minter’s XCP is automatically refunded.",
"Finish launching {asset}",
"The inscription commit for {asset} is broadcast, but its reveal is not. The launch exists only once the reveal is on-chain, and until then the commit's BTC waits in an output only that reveal can spend.",
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch."
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.",
"No expiry"
]
}
3 changes: 2 additions & 1 deletion apps/web/src/locales/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -1293,5 +1293,6 @@
"If it fails, every minter’s XCP is automatically refunded.": "Se não atingir a meta, todo o XCP de cada participante é devolvido automaticamente.",
"Finish launching {asset}": "Concluir o lançamento de {asset}",
"The inscription commit for {asset} is broadcast, but its reveal is not. The launch exists only once the reveal is on-chain, and until then the commit's BTC waits in an output only that reveal can spend.": "O commit da inscrição de {asset} foi transmitido, mas o reveal não. O lançamento só existe quando o reveal está on-chain e, até lá, o BTC do commit espera numa saída que só esse reveal pode gastar.",
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.": "O commit da inscrição de {asset} nunca chegou à chain, e uma das moedas que ele gasta já foi gasta por outra transação confirmada, então nunca vai chegar. Nenhum BTC dele espera um reveal, e você pode começar um novo lançamento."
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.": "O commit da inscrição de {asset} nunca chegou à chain, e uma das moedas que ele gasta já foi gasta por outra transação confirmada, então nunca vai chegar. Nenhum BTC dele espera um reveal, e você pode começar um novo lançamento.",
"No expiry": "Sem expiração"
}
3 changes: 2 additions & 1 deletion apps/web/src/locales/pt.status.json
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,7 @@
"If it fails, every minter’s XCP is automatically refunded.",
"Finish launching {asset}",
"The inscription commit for {asset} is broadcast, but its reveal is not. The launch exists only once the reveal is on-chain, and until then the commit's BTC waits in an output only that reveal can spend.",
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch."
"The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch.",
"No expiry"
]
}
Loading
Loading