aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-03-13 14:25:51 -0700
committerAdam Soltys <[email protected]>2026-03-13 14:25:51 -0700
commit91f0517b8d72a2a45c7f6423597808b2e4a6f0aa (patch)
tree5cd92fc6aeb65307508e726ffbace0c1549700b8
parent7e0dab611ea6d6a6f764470af9b0c53055e05d74 (diff)
downloadcoinos-ui-91f0517b8d72a2a45c7f6423597808b2e4a6f0aa.tar.gz
coinos-ui-91f0517b8d72a2a45c7f6423597808b2e4a6f0aa.zip
delegation
-rw-r--r--src/lib/ark.ts34
-rw-r--r--src/routes/(app)/payment/[id]/+page.svelte26
-rw-r--r--src/routes/(app)/send/ark/[address]/+layout.server.ts7
-rw-r--r--src/routes/(app)/send/ark/[address]/+page.server.ts7
-rw-r--r--src/routes/(app)/send/ark/[address]/[amount]/[...feeRate]/+page.server.ts8
-rw-r--r--src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte1
6 files changed, 49 insertions, 34 deletions
diff --git a/src/lib/ark.ts b/src/lib/ark.ts
index a848e5c7..42ab822a 100644
--- a/src/lib/ark.ts
+++ b/src/lib/ark.ts
@@ -7,6 +7,8 @@ export const arkServerUrl = {
bitcoin: "https://arkade.computer",
regtest: "http://localhost:7070",
}[PUBLIC_COINOS_NETWORK || "regtest"];
+// Delegator runs on the coinos server, accessed via /api proxy
+const delegatorUrl = "/api";
export const arkkey = persistLocal("arkkey", "");
export const arkaid = persistLocal("arkaid", "");
@@ -53,12 +55,14 @@ export const getWallet = async () => {
}
if (walletInstance && walletKey === key) return walletInstance;
- const { SingleKey, Wallet } = await loadArkSdk();
+ const { SingleKey, Wallet, RestDelegatorProvider } = await loadArkSdk();
const identity = SingleKey.fromHex(key);
+ const delegatorProvider = new RestDelegatorProvider(delegatorUrl);
walletInstance = await Wallet.create({
identity,
arkServerUrl,
+ delegatorProvider,
});
walletKey = key;
return walletInstance;
@@ -305,6 +309,7 @@ const _syncTransactions = async (aid: string) => {
const result = await post("/ark/sync", { transactions, aid, balance, arkAddress: walletAddr });
cacheVaultSnapshot(); // fire-and-forget
+ delegateVtxos(); // fire-and-forget
return result;
};
@@ -496,6 +501,8 @@ export const refresh = async () => {
const vtxos = await wallet.getVtxos({ spendableOnly: false });
if (vtxos?.length) addProcessedVtxos(vtxos.map(vtxoKey));
}
+
+ delegateVtxos(); // fire-and-forget
};
export const settle = async () => {
@@ -511,6 +518,31 @@ export const settle = async () => {
// ignores renewed VTXOs (they get new txids after an Ark round)
const vtxos = await wallet.getVtxos({ spendableOnly: false });
if (vtxos?.length) addProcessedVtxos(vtxos.map(vtxoKey));
+
+ delegateVtxos(); // fire-and-forget
+};
+
+export const delegateVtxos = async () => {
+ try {
+ const wallet = await getWallet();
+ if (!wallet) return;
+ if (!wallet.delegatorManager) return;
+
+ const vtxos = await wallet.getVtxos({ spendableOnly: true });
+ if (!vtxos?.length) return;
+
+ const address = await wallet.getAddress();
+ const { delegated, failed } = await wallet.delegatorManager.delegate(vtxos, address);
+
+ if (delegated.length > 0) {
+ console.log("[ark] delegated", delegated.length, "vtxos for renewal");
+ }
+ if (failed.length > 0) {
+ console.warn("[ark] delegation failed for", failed.length, "groups");
+ }
+ } catch (e: any) {
+ console.warn("[ark] delegation failed:", e.message);
+ }
};
// Service Worker wallet for background fund notifications
diff --git a/src/routes/(app)/payment/[id]/+page.svelte b/src/routes/(app)/payment/[id]/+page.svelte
index 03023e8a..3b41cc4f 100644
--- a/src/routes/(app)/payment/[id]/+page.svelte
+++ b/src/routes/(app)/payment/[id]/+page.svelte
@@ -249,17 +249,6 @@
{@render copyable("Child Txid", p.childTxid, `${expl}/tx/${p.childTxid}`)}
{/if}
- {#if canBump}
- <div class="py-4 border-b border-base-300 space-y-2">
- <button type="button" class="btn btn-accent w-full" onclick={bump} disabled={bumpLoading}>
- {bumpLoading ? "Bumping..." : "Speed up"}
- </button>
- {#if bumpError}
- <div class="text-red-600 text-sm text-center">{bumpError}</div>
- {/if}
- </div>
- {/if}
-
{#if type === types.lightning || type === types.bolt12}
{@render copyable($t("payments.invoice"), hash)}
{@render copyable($t("payments.preimage"), ref)}
@@ -277,8 +266,23 @@
{@render copyable("Address", hash, `${expl}/address/${hash}`)}
{/if}
+ {#if (type === "bitcoin" || type === "liquid") && amount < 0 && p.address}
+ {@render copyable("Address", p.address, `${expl}/address/${p.address}`)}
+ {/if}
+
{#if path}
{@render copyable("Path", path)}
{/if}
+
+ {#if canBump}
+ <div class="py-4 space-y-2">
+ <button type="button" class="btn btn-accent w-full" onclick={bump} disabled={bumpLoading}>
+ {bumpLoading ? "Bumping..." : "Speed up"}
+ </button>
+ {#if bumpError}
+ <div class="text-red-600 text-sm text-center">{bumpError}</div>
+ {/if}
+ </div>
+ {/if}
</div>
</div>
diff --git a/src/routes/(app)/send/ark/[address]/+layout.server.ts b/src/routes/(app)/send/ark/[address]/+layout.server.ts
index 18fb7aed..b17d89bc 100644
--- a/src/routes/(app)/send/ark/[address]/+layout.server.ts
+++ b/src/routes/(app)/send/ark/[address]/+layout.server.ts
@@ -7,13 +7,6 @@ export async function load({ cookies, params, parent, url }) {
const { address, amount } = params;
let account = await get(`/account/${aid}`, auth(cookies));
- // Fall back to custodial if cookie points to ark account
- if (account.type === "ark" && aid !== user.id) {
- aid = user.id;
- account = await get(`/account/${aid}`, auth(cookies));
- cookies.set("aid", aid, { path: "/", maxAge: 86400, httpOnly: false });
- }
-
let invoice;
try {
invoice = await get(`/invoice/${address}`);
diff --git a/src/routes/(app)/send/ark/[address]/+page.server.ts b/src/routes/(app)/send/ark/[address]/+page.server.ts
index 83a5050f..086e6daa 100644
--- a/src/routes/(app)/send/ark/[address]/+page.server.ts
+++ b/src/routes/(app)/send/ark/[address]/+page.server.ts
@@ -7,12 +7,5 @@ export async function load({ cookies, parent, url }) {
let aid = url.searchParams.get("aid") || cookies.get("aid") || user.id;
let account = await get(`/account/${aid}`, auth(cookies));
- // Fall back to custodial if cookie points to ark account
- if (account.type === "ark" && aid !== user.id) {
- aid = user.id;
- account = await get(`/account/${aid}`, auth(cookies));
- cookies.set("aid", aid, { path: "/", maxAge: 86400, httpOnly: false });
- }
-
return { balance: account.balance, rate: rates[user.currency] };
}
diff --git a/src/routes/(app)/send/ark/[address]/[amount]/[...feeRate]/+page.server.ts b/src/routes/(app)/send/ark/[address]/[amount]/[...feeRate]/+page.server.ts
index ee0775d3..37a0f068 100644
--- a/src/routes/(app)/send/ark/[address]/[amount]/[...feeRate]/+page.server.ts
+++ b/src/routes/(app)/send/ark/[address]/[amount]/[...feeRate]/+page.server.ts
@@ -9,14 +9,6 @@ export async function load({ params: { address, amount }, cookies, parent, url }
let account = await get(`/account/${aid}`, auth(cookies));
- // If cookie points to an ark account but user is sending TO an ark address,
- // fall back to custodial account — ark-to-ark sends use client-side wallet
- if (account.type === "ark" && aid !== user.id) {
- aid = user.id;
- account = await get(`/account/${aid}`, auth(cookies));
- cookies.set("aid", aid, { path: "/", maxAge: 86400, httpOnly: false });
- }
-
if (account.type === "bitcoin") {
const inv = await post(
"/invoice",
diff --git a/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte b/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte
index 86bad61c..7b2c9ccf 100644
--- a/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte
+++ b/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte
@@ -281,6 +281,7 @@
<form method="POST" use:enhance={handler}>
<input name="pin" value={$pin} type="hidden" />
+ <input name="address" value={address} type="hidden" />
<input name="hex" value={hex} type="hidden" />
<input name="rate" value={$rate} type="hidden" />
<input name="aid" value={account.id} type="hidden" />