@trustless-work/blocks 1.2.1 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/bin/index.js +326 -105
  2. package/package.json +1 -1
  3. package/templates/dashboard/dashboard-01/useDashboard.ts +1 -1
  4. package/templates/dashboard/deps.json +8 -0
  5. package/templates/deps.json +12 -26
  6. package/templates/escrows/deps.json +30 -0
  7. package/templates/escrows/details/Actions.tsx +46 -45
  8. package/templates/escrows/details/MilestoneCard.tsx +27 -15
  9. package/templates/escrows/details/MilestoneDetailDialog.tsx +2 -2
  10. package/templates/escrows/details/SuccessReleaseDialog.tsx +1 -1
  11. package/templates/escrows/details/useDetailsEscrow.ts +1 -1
  12. package/templates/escrows/escrows-by-role/useEscrowsByRole.shared.ts +1 -1
  13. package/templates/escrows/escrows-by-signer/useEscrowsBySigner.shared.ts +1 -1
  14. package/templates/escrows/multi-release/dispute-milestone/button/DisputeMilestone.tsx +1 -1
  15. package/templates/escrows/multi-release/dispute-milestone/shared/useDisputeMilestone.ts +1 -1
  16. package/templates/escrows/multi-release/initialize-escrow/shared/useInitializeEscrow.ts +1 -1
  17. package/templates/escrows/multi-release/release-milestone/button/ReleaseMilestone.tsx +1 -1
  18. package/templates/escrows/multi-release/release-milestone/shared/useReleaseMilestone.ts +1 -1
  19. package/templates/escrows/multi-release/resolve-dispute/button/ResolveDispute.tsx +1 -1
  20. package/templates/escrows/multi-release/resolve-dispute/shared/useResolveDispute.ts +1 -1
  21. package/templates/escrows/multi-release/update-escrow/shared/useUpdateEscrow.ts +1 -1
  22. package/templates/escrows/multi-release/withdraw-remaining-funds/button/WithdrawRemainingFunds.tsx +1 -1
  23. package/templates/escrows/multi-release/withdraw-remaining-funds/shared/useWithdrawRemainingFunds.ts +1 -1
  24. package/templates/escrows/single-multi-release/approve-milestone/button/ApproveMilestone.tsx +1 -1
  25. package/templates/escrows/single-multi-release/approve-milestone/shared/useApproveMilestone.ts +1 -1
  26. package/templates/escrows/single-multi-release/change-milestone-status/button/ChangeMilestoneStatus.tsx +1 -1
  27. package/templates/escrows/single-multi-release/change-milestone-status/shared/useChangeMilestoneStatus.ts +1 -1
  28. package/templates/escrows/single-multi-release/fund-escrow/button/FundEscrow.tsx +1 -1
  29. package/templates/escrows/single-multi-release/fund-escrow/shared/useFundEscrow.ts +1 -1
  30. package/templates/escrows/single-release/dispute-escrow/button/DisputeEscrow.tsx +1 -1
  31. package/templates/escrows/single-release/initialize-escrow/shared/useInitializeEscrow.ts +1 -1
  32. package/templates/escrows/single-release/release-escrow/button/ReleaseEscrow.tsx +1 -1
  33. package/templates/escrows/single-release/resolve-dispute/button/ResolveDispute.tsx +1 -1
  34. package/templates/escrows/single-release/resolve-dispute/shared/useResolveDispute.ts +1 -1
  35. package/templates/escrows/single-release/update-escrow/shared/useUpdateEscrow.ts +1 -1
  36. package/templates/handle-errors/deps.json +7 -0
  37. package/templates/helpers/deps.json +5 -0
  38. package/templates/providers/deps.json +8 -0
  39. package/templates/tanstack/deps.json +8 -0
  40. package/templates/wallet-kit/WalletButtons.tsx +1 -1
  41. package/templates/wallet-kit/deps.json +7 -0
  42. package/templates/wallet-kit/trustlines.ts +3 -3
  43. package/templates/wallet-kit/useWallet.ts +1 -1
  44. /package/templates/{wallet-kit → providers}/WalletProvider.tsx +0 -0
package/bin/index.js CHANGED
@@ -157,8 +157,81 @@ function readProjectPackageJson() {
157
157
  }
158
158
  }
159
159
 
160
+ /**
161
+ * Returns the set of npm package names already present in the user's package.json
162
+ * (both dependencies and devDependencies). Used to avoid reinstalling what already exists.
163
+ */
164
+ function getInstalledPackages() {
165
+ const pkg = readProjectPackageJson();
166
+ if (!pkg) return new Set();
167
+ return new Set([
168
+ ...Object.keys(pkg.dependencies || {}),
169
+ ...Object.keys(pkg.devDependencies || {}),
170
+ ]);
171
+ }
172
+
173
+ /**
174
+ * Returns the set of shadcn component names already installed in the user's project
175
+ * by scanning the UI components directory (derived from .twblocks.json uiBase).
176
+ */
177
+ function getInstalledShadcnComponents() {
178
+ const config = loadConfig();
179
+ const uiBase = config.uiBase || "@/components/ui";
180
+ const uiRelative = uiBase.replace(/^@\//, "src/");
181
+ const uiDir = path.join(PROJECT_ROOT, uiRelative);
182
+ if (!fs.existsSync(uiDir)) return new Set();
183
+ try {
184
+ const files = fs.readdirSync(uiDir);
185
+ return new Set(files.map((f) => f.replace(/\.(tsx?|jsx?)$/, "")));
186
+ } catch {
187
+ return new Set();
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Resolves the deps.json for a given block by walking up the template directory tree.
193
+ * This allows sub-blocks (e.g. escrows/single-release/initialize-escrow) to inherit
194
+ * from their parent block's deps.json (e.g. escrows/deps.json).
195
+ *
196
+ * Falls back to the global templates/deps.json if no block-specific file is found.
197
+ */
198
+ function resolveBlockDeps(blockName) {
199
+ const normalizedBase = TEMPLATES_DIR.split(path.sep).join("/");
200
+ let dir = path.join(TEMPLATES_DIR, blockName);
201
+
202
+ while (dir.split(path.sep).join("/").startsWith(normalizedBase)) {
203
+ const candidate = path.join(dir, "deps.json");
204
+ if (fs.existsSync(candidate)) {
205
+ try {
206
+ return JSON.parse(fs.readFileSync(candidate, "utf8"));
207
+ } catch {
208
+ // Malformed JSON — keep walking up
209
+ }
210
+ }
211
+ const parent = path.dirname(dir);
212
+ if (parent === dir) break; // filesystem root
213
+ dir = parent;
214
+ }
215
+
216
+ // Fallback to global deps.json
217
+ if (fs.existsSync(GLOBAL_DEPS_FILE)) {
218
+ try {
219
+ return JSON.parse(fs.readFileSync(GLOBAL_DEPS_FILE, "utf8"));
220
+ } catch {
221
+ return { dependencies: {}, devDependencies: {}, shadcnComponents: [] };
222
+ }
223
+ }
224
+
225
+ return { dependencies: {}, devDependencies: {}, shadcnComponents: [] };
226
+ }
227
+
228
+ /**
229
+ * Installs npm dependencies, filtering out packages that are already installed
230
+ * in the user's project and packages in the BLOCKED set (installed via other means).
231
+ */
160
232
  function installDeps({ dependencies = {}, devDependencies = {} }) {
161
233
  const pm = detectPM();
234
+ const installed = getInstalledPackages();
162
235
  const BLOCKED = new Set([
163
236
  "tailwindcss",
164
237
  "@tailwindcss/cli",
@@ -169,11 +242,12 @@ function installDeps({ dependencies = {}, devDependencies = {} }) {
169
242
  "postcss-import",
170
243
  "@creit-tech/stellar-wallets-kit",
171
244
  ]);
245
+
172
246
  const depList = Object.entries(dependencies)
173
- .filter(([k]) => !BLOCKED.has(k))
247
+ .filter(([k]) => !BLOCKED.has(k) && !installed.has(k))
174
248
  .map(([k, v]) => `${k}@${v}`);
175
249
  const devList = Object.entries(devDependencies)
176
- .filter(([k]) => !BLOCKED.has(k))
250
+ .filter(([k]) => !BLOCKED.has(k) && !installed.has(k))
177
251
  .map(([k, v]) => `${k}@${v}`);
178
252
 
179
253
  if (depList.length) {
@@ -191,6 +265,75 @@ function installDeps({ dependencies = {}, devDependencies = {} }) {
191
265
  }
192
266
  }
193
267
 
268
+ /**
269
+ * Installs only the shadcn components that are not yet present in the user's project.
270
+ */
271
+ async function installShadcnComponents(components = []) {
272
+ if (!components.length) return;
273
+ const installed = getInstalledShadcnComponents();
274
+ const missing = components.filter((c) => !installed.has(c));
275
+ if (!missing.length) return;
276
+ // Suppress stdout from shadcn CLI (it prints noisy wrapper instructions).
277
+ // Errors still go to stderr so failures are visible.
278
+ return new Promise((resolve, reject) => {
279
+ const child = spawn("npx", ["shadcn@latest", "add", ...missing], {
280
+ stdio: ["inherit", "pipe", "pipe"],
281
+ cwd: PROJECT_ROOT,
282
+ shell: true,
283
+ });
284
+ child.on("close", (code) => {
285
+ if (code === 0) resolve();
286
+ else reject(new Error(`shadcn add exited with code ${code}`));
287
+ });
288
+ });
289
+ }
290
+
291
+ /**
292
+ * Orchestrates the full dependency installation for a given block:
293
+ * 1. Resolves the block's deps.json
294
+ * 2. Installs missing npm dependencies
295
+ * 3. Installs missing shadcn components
296
+ * 4. Handles JSR-based packages (stellar-wallets-kit)
297
+ */
298
+ async function installBlockDeps(blockName) {
299
+ const meta = resolveBlockDeps(blockName);
300
+ const hasDeps =
301
+ Object.keys(meta.dependencies || {}).length > 0 ||
302
+ Object.keys(meta.devDependencies || {}).length > 0;
303
+ const hasShadcn =
304
+ Array.isArray(meta.shadcnComponents) && meta.shadcnComponents.length > 0;
305
+
306
+ if (!hasDeps && !hasShadcn) return;
307
+
308
+ if (hasShadcn) {
309
+ await withSpinner("Installing required shadcn/ui components", async () => {
310
+ await installShadcnComponents(meta.shadcnComponents);
311
+ });
312
+ }
313
+
314
+ if (hasDeps) {
315
+ await withSpinner("Installing required dependencies", async () => {
316
+ installDeps(meta);
317
+ });
318
+
319
+ // Handle JSR-based package separately
320
+ if (
321
+ meta.dependencies &&
322
+ meta.dependencies["@creit-tech/stellar-wallets-kit"]
323
+ ) {
324
+ const installed = getInstalledPackages();
325
+ if (!installed.has("@creit-tech/stellar-wallets-kit")) {
326
+ await withSpinner(
327
+ "Installing @creit-tech/stellar-wallets-kit from JSR",
328
+ async () => {
329
+ run("npx", ["jsr", "add", "@creit-tech/stellar-wallets-kit"]);
330
+ }
331
+ );
332
+ }
333
+ }
334
+ }
335
+ }
336
+
194
337
  function loadConfig() {
195
338
  const cfgPath = path.join(PROJECT_ROOT, ".twblocks.json");
196
339
  if (fs.existsSync(cfgPath)) {
@@ -214,11 +357,117 @@ function parseFlags(argv) {
214
357
  i++;
215
358
  } else if (a === "--install" || a === "-i") {
216
359
  flags.install = true;
360
+ } else if (a === "--no-install") {
361
+ flags.noInstall = true;
217
362
  }
218
363
  }
219
364
  return flags;
220
365
  }
221
366
 
367
+ /**
368
+ * Declarative map of peer dependencies per block prefix.
369
+ * When a block is added, ALL matching prefixes are merged so sub-blocks
370
+ * inherit from their parent prefix.
371
+ *
372
+ * - blocks: other template directories to auto-copy (wallet-kit, tanstack, etc.)
373
+ * - providers: individual provider files to auto-copy (EscrowProvider, etc.)
374
+ */
375
+ const PEER_DEPS = {
376
+ // Root escrows bundle — copies ALL sub-blocks, so needs ALL providers
377
+ escrows: {
378
+ blocks: ["helpers", "handle-errors", "wallet-kit", "tanstack"],
379
+ providers: [
380
+ "EscrowProvider",
381
+ "EscrowDialogsProvider",
382
+ "EscrowAmountProvider",
383
+ "WalletProvider",
384
+ "ReactQueryClientProvider",
385
+ "TrustlessWork",
386
+ ],
387
+ },
388
+ // Bundle: single-release includes release-escrow which needs Dialogs + Amount
389
+ "escrows/single-release": {
390
+ providers: ["EscrowDialogsProvider", "EscrowAmountProvider"],
391
+ },
392
+ // Bundle: multi-release includes release-milestone which needs Dialogs + Amount
393
+ "escrows/multi-release": {
394
+ providers: ["EscrowDialogsProvider", "EscrowAmountProvider"],
395
+ },
396
+ // Individual sub-blocks
397
+ "escrows/escrows-by-role": {
398
+ providers: ["EscrowDialogsProvider"],
399
+ },
400
+ "escrows/escrows-by-signer": {
401
+ providers: ["EscrowDialogsProvider"],
402
+ },
403
+ "escrows/details": {
404
+ providers: ["EscrowDialogsProvider", "EscrowAmountProvider"],
405
+ },
406
+ "escrows/single-release/release-escrow": {
407
+ providers: ["EscrowDialogsProvider", "EscrowAmountProvider"],
408
+ },
409
+ "escrows/multi-release/release-milestone": {
410
+ providers: ["EscrowDialogsProvider", "EscrowAmountProvider"],
411
+ },
412
+ // Dashboard
413
+ dashboard: {
414
+ blocks: ["helpers", "wallet-kit", "tanstack"],
415
+ providers: ["WalletProvider", "ReactQueryClientProvider", "TrustlessWork"],
416
+ },
417
+ // Tanstack needs wallet-kit
418
+ tanstack: {
419
+ blocks: ["wallet-kit"],
420
+ },
421
+ // Wallet-kit needs WalletProvider
422
+ "wallet-kit": {
423
+ providers: ["WalletProvider"],
424
+ },
425
+ };
426
+
427
+ /**
428
+ * Resolves all peer dependencies for a given block name by matching
429
+ * every applicable prefix in PEER_DEPS and merging the results.
430
+ *
431
+ * Example: "escrows/escrows-by-role/table" matches both "escrows"
432
+ * and "escrows/escrows-by-role", returning their merged blocks + providers.
433
+ */
434
+ function resolvePeerDeps(blockName) {
435
+ const blocks = new Set();
436
+ const providers = new Set();
437
+ for (const [prefix, deps] of Object.entries(PEER_DEPS)) {
438
+ if (blockName === prefix || blockName.startsWith(prefix + "/")) {
439
+ (deps.blocks || []).forEach((b) => blocks.add(b));
440
+ (deps.providers || []).forEach((p) => providers.add(p));
441
+ }
442
+ }
443
+ return { blocks: [...blocks], providers: [...providers] };
444
+ }
445
+
446
+ /**
447
+ * Copies a single provider file from templates/providers/ to the user's
448
+ * tw-blocks/providers/ directory. Skips if the file already exists.
449
+ */
450
+ function copyProviderFile(providerName, { uiBase } = {}) {
451
+ const srcFile = path.join(TEMPLATES_DIR, "providers", providerName + ".tsx");
452
+ if (!fs.existsSync(srcFile)) return;
453
+
454
+ const componentsSrcDir = path.join(PROJECT_ROOT, "src", "components");
455
+ const outRoot = fs.existsSync(componentsSrcDir)
456
+ ? path.join(componentsSrcDir, "tw-blocks")
457
+ : path.join(PROJECT_ROOT, "components", "tw-blocks");
458
+
459
+ const destFile = path.join(outRoot, "providers", providerName + ".tsx");
460
+ if (fs.existsSync(destFile)) return; // already present, skip
461
+
462
+ fs.mkdirSync(path.dirname(destFile), { recursive: true });
463
+ const config = loadConfig();
464
+ const effectiveUiBase = uiBase || config.uiBase || "@/components/ui";
465
+ const raw = fs.readFileSync(srcFile, "utf8");
466
+ const transformed = raw.replaceAll("__UI_BASE__", effectiveUiBase);
467
+ fs.writeFileSync(destFile, transformed, "utf8");
468
+ console.log(`✅ ${path.relative(PROJECT_ROOT, destFile)} created`);
469
+ }
470
+
222
471
  function copyTemplate(name, { uiBase, shouldInstall = false } = {}) {
223
472
  const srcFile = path.join(TEMPLATES_DIR, `${name}.tsx`);
224
473
  const requestedDir = path.join(TEMPLATES_DIR, name);
@@ -419,12 +668,17 @@ function copyTemplate(name, { uiBase, shouldInstall = false } = {}) {
419
668
  for (const v of variants) copyVariant(v);
420
669
  }
421
670
 
422
- if (shouldInstall && fs.existsSync(GLOBAL_DEPS_FILE)) {
423
- const meta = JSON.parse(fs.readFileSync(GLOBAL_DEPS_FILE, "utf8"));
671
+ if (shouldInstall) {
672
+ const meta = resolveBlockDeps(name);
424
673
  installDeps(meta);
425
- // Install @creit-tech/stellar-wallets-kit using jsr after all other deps are installed
426
- if (meta.dependencies && meta.dependencies["@creit-tech/stellar-wallets-kit"]) {
427
- run("npx", ["jsr", "add", "@creit-tech/stellar-wallets-kit"]);
674
+ if (
675
+ meta.dependencies &&
676
+ meta.dependencies["@creit-tech/stellar-wallets-kit"]
677
+ ) {
678
+ const installed = getInstalledPackages();
679
+ if (!installed.has("@creit-tech/stellar-wallets-kit")) {
680
+ run("npx", ["jsr", "add", "@creit-tech/stellar-wallets-kit"]);
681
+ }
428
682
  }
429
683
  }
430
684
  currentEscrowType = null;
@@ -1463,12 +1717,17 @@ function copyTemplate(name, { uiBase, shouldInstall = false } = {}) {
1463
1717
  process.exit(1);
1464
1718
  }
1465
1719
 
1466
- if (shouldInstall && fs.existsSync(GLOBAL_DEPS_FILE)) {
1467
- const meta = JSON.parse(fs.readFileSync(GLOBAL_DEPS_FILE, "utf8"));
1720
+ if (shouldInstall) {
1721
+ const meta = resolveBlockDeps(name);
1468
1722
  installDeps(meta);
1469
- // Install @creit-tech/stellar-wallets-kit using jsr after all other deps are installed
1470
- if (meta.dependencies && meta.dependencies["@creit-tech/stellar-wallets-kit"]) {
1471
- run("npx", ["jsr", "add", "@creit-tech/stellar-wallets-kit"]);
1723
+ if (
1724
+ meta.dependencies &&
1725
+ meta.dependencies["@creit-tech/stellar-wallets-kit"]
1726
+ ) {
1727
+ const installed = getInstalledPackages();
1728
+ if (!installed.has("@creit-tech/stellar-wallets-kit")) {
1729
+ run("npx", ["jsr", "add", "@creit-tech/stellar-wallets-kit"]);
1730
+ }
1472
1731
  }
1473
1732
  }
1474
1733
  }
@@ -1770,7 +2029,7 @@ function cleanJsrDeps() {
1770
2029
 
1771
2030
  if (args[0] === "init") {
1772
2031
  cleanJsrDeps();
1773
- console.log("\n▶ Setting up shadcn/ui components...");
2032
+ console.log("\n▶ Setting up shadcn/ui base configuration...");
1774
2033
  const doInit = await promptYesNo("Run shadcn init now?", true);
1775
2034
  if (doInit) {
1776
2035
  run("npx", ["shadcn@latest", "init"]);
@@ -1778,66 +2037,11 @@ if (args[0] === "init") {
1778
2037
  console.log("\x1b[90m– Skipped shadcn init\x1b[0m");
1779
2038
  }
1780
2039
 
1781
- const addShadcn = await promptYesNo(
1782
- "Add shadcn components (button, input, form, card, sonner, checkbox, dialog, textarea, sonner, select, table, calendar, popover, separator, calendar-05, badge, sheet, tabs, avatar, tooltip, progress, chart, empty)?",
1783
- true
1784
- );
1785
- if (addShadcn) {
1786
- await withSpinner("Installing shadcn/ui components", async () => {
1787
- await runAsync("npx", [
1788
- "shadcn@latest",
1789
- "add",
1790
- "button",
1791
- "input",
1792
- "form",
1793
- "card",
1794
- "sonner",
1795
- "checkbox",
1796
- "dialog",
1797
- "textarea",
1798
- "sonner",
1799
- "select",
1800
- "table",
1801
- "calendar",
1802
- "popover",
1803
- "separator",
1804
- "calendar-05",
1805
- "badge",
1806
- "sheet",
1807
- "tabs",
1808
- "avatar",
1809
- "tooltip",
1810
- "progress",
1811
- "chart",
1812
- "empty",
1813
- ]);
1814
- });
1815
- } else {
1816
- console.log("\x1b[90m– Skipped adding shadcn components\x1b[0m");
1817
- }
2040
+ // Install sonner (toast notifications) — used across many blocks as a peer utility
2041
+ await withSpinner("Installing sonner (toast notifications)", async () => {
2042
+ await installShadcnComponents(["sonner"]);
2043
+ });
1818
2044
 
1819
- if (!fs.existsSync(GLOBAL_DEPS_FILE)) {
1820
- console.error("❌ deps.json not found in templates/");
1821
- process.exit(1);
1822
- }
1823
- const meta = JSON.parse(fs.readFileSync(GLOBAL_DEPS_FILE, "utf8"));
1824
- const installLibs = await promptYesNo(
1825
- "Install (react-hook-form, @tanstack/react-query, @tanstack/react-query-devtools, @trustless-work/escrow, @hookform/resolvers, axios, @creit-tech/stellar-wallets-kit, react-day-picker, recharts & zod) dependencies now?",
1826
- true
1827
- );
1828
- if (installLibs) {
1829
- await withSpinner("Installing required dependencies", async () => {
1830
- installDeps(meta);
1831
- });
1832
- // Install @creit-tech/stellar-wallets-kit using jsr after all other deps are installed
1833
- if (meta.dependencies && meta.dependencies["@creit-tech/stellar-wallets-kit"]) {
1834
- await withSpinner("Installing @creit-tech/stellar-wallets-kit from JSR", async () => {
1835
- run("npx", ["jsr", "add", "@creit-tech/stellar-wallets-kit"]);
1836
- });
1837
- }
1838
- } else {
1839
- console.log("\x1b[90m– Skipped installing required dependencies\x1b[0m");
1840
- }
1841
2045
  const cfgPath = path.join(PROJECT_ROOT, ".twblocks.json");
1842
2046
  if (!fs.existsSync(cfgPath)) {
1843
2047
  fs.writeFileSync(
@@ -1851,32 +2055,16 @@ if (args[0] === "init") {
1851
2055
  )} with default uiBase`
1852
2056
  );
1853
2057
  }
1854
- console.log("\x1b[32m✔\x1b[0m shadcn/ui components step completed");
2058
+ // Always copy helpers — they are a base utility used by escrows, dashboard, and others
2059
+ await withSpinner("Copying helpers", async () => {
2060
+ copyTemplate("helpers");
2061
+ });
1855
2062
 
1856
- const wantProviders = await promptYesNo(
1857
- "Install TanStack Query and Trustless Work providers and wrap app/layout with them?",
1858
- true
2063
+ logCheck("Base setup completed");
2064
+
2065
+ console.log(
2066
+ `\n${COLORS.gray}Note: Dependencies and shadcn/ui components will be installed automatically when you add blocks via 'trustless-work add <block>'.${COLORS.reset}\n`
1859
2067
  );
1860
- if (wantProviders) {
1861
- await withSpinner("Installing providers", async () => {
1862
- copyTemplate("providers");
1863
- });
1864
- const layoutPath = findLayoutFile();
1865
- if (layoutPath) {
1866
- await withSpinner("Updating app/layout with providers", async () => {
1867
- injectProvidersIntoLayout(layoutPath, {
1868
- reactQuery: true,
1869
- trustless: true,
1870
- });
1871
- });
1872
- } else {
1873
- console.warn(
1874
- "⚠️ Could not find app/layout file. Skipped automatic wiring."
1875
- );
1876
- }
1877
- } else {
1878
- console.log("\x1b[90m– Skipped installing providers\x1b[0m");
1879
- }
1880
2068
 
1881
2069
  printBannerTRUSTLESSWORK();
1882
2070
  console.log("\n\nResources");
@@ -1924,7 +2112,7 @@ if (args[0] === "init") {
1924
2112
  const cfgPath = path.join(PROJECT_ROOT, ".twblocks.json");
1925
2113
  if (!fs.existsSync(cfgPath)) {
1926
2114
  console.error(
1927
- "❌ Missing initial setup. Run 'trustless-work init' first to install dependencies and create .twblocks.json (uiBase)."
2115
+ "❌ Missing initial setup. Run 'trustless-work init' first to create .twblocks.json (uiBase)."
1928
2116
  );
1929
2117
  console.error(
1930
2118
  " After init, re-run: trustless-work add " +
@@ -1933,16 +2121,42 @@ if (args[0] === "init") {
1933
2121
  );
1934
2122
  process.exit(1);
1935
2123
  }
2124
+
2125
+ // Auto-install block-specific dependencies and shadcn components (unless --no-install)
2126
+ if (!flags.noInstall) {
2127
+ await installBlockDeps(args[1]);
2128
+ }
2129
+
1936
2130
  copyTemplate(args[1], {
1937
2131
  uiBase: flags.uiBase,
1938
- shouldInstall: !!flags.install,
2132
+ shouldInstall: false, // deps already handled above by installBlockDeps
1939
2133
  });
1940
2134
 
1941
- // Post-add wiring for specific templates
1942
- const layoutPath = findLayoutFile();
1943
- if (layoutPath) {
1944
- if (args[1] === "wallet-kit" || args[1].startsWith("wallet-kit/")) {
1945
- injectProvidersIntoLayout(layoutPath, { wallet: true });
2135
+ // Auto-resolve and copy peer block dependencies + individual provider files
2136
+ const componentsSrcDir = path.join(PROJECT_ROOT, "src", "components");
2137
+ const peerOutRoot = fs.existsSync(componentsSrcDir)
2138
+ ? path.join(componentsSrcDir, "tw-blocks")
2139
+ : path.join(PROJECT_ROOT, "components", "tw-blocks");
2140
+
2141
+ const { blocks: peerBlocks, providers: peerProviders } = resolvePeerDeps(
2142
+ args[1]
2143
+ );
2144
+
2145
+ for (const peer of peerBlocks) {
2146
+ const peerDir = path.join(peerOutRoot, peer);
2147
+ if (fs.existsSync(peerDir)) continue;
2148
+ if (!flags.noInstall) {
2149
+ await installBlockDeps(peer);
2150
+ }
2151
+ copyTemplate(peer, { uiBase: flags.uiBase, shouldInstall: false });
2152
+ }
2153
+
2154
+ if (peerProviders.length) {
2155
+ if (!flags.noInstall) {
2156
+ await installBlockDeps("providers");
2157
+ }
2158
+ for (const provider of peerProviders) {
2159
+ copyProviderFile(provider, { uiBase: flags.uiBase });
1946
2160
  }
1947
2161
  }
1948
2162
 
@@ -1984,12 +2198,19 @@ if (args[0] === "init") {
1984
2198
  Usage:
1985
2199
 
1986
2200
  trustless-work init
1987
- trustless-work add <template> [--install]
2201
+ trustless-work add <template> [--no-install]
1988
2202
 
1989
2203
  Options:
1990
2204
 
1991
2205
  --ui-base <path> Base import path to your shadcn/ui components (default: "@/components/ui")
1992
- --install, -i Also install dependencies (normally use 'init' once instead)
2206
+ --no-install Skip automatic dependency and shadcn component installation
2207
+ --install, -i (Legacy) Explicitly install deps when using copyTemplate directly
2208
+
2209
+ Notes:
2210
+
2211
+ - 'init' sets up shadcn base config and .twblocks.json. It does NOT install all deps upfront.
2212
+ - 'add' automatically installs only the npm deps and shadcn components required by the block.
2213
+ - Already-installed packages and components are detected and skipped.
1993
2214
 
1994
2215
  Examples:
1995
2216
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trustless-work/blocks",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "author": "Trustless Work",
5
5
  "keywords": [
6
6
  "react",
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import React from "react";
4
- import { useWalletContext } from "../../wallet-kit/WalletProvider";
4
+ import { useWalletContext } from "../../providers/WalletProvider";
5
5
  import { useEscrowsBySignerQuery } from "../../tanstack/useEscrowsBySignerQuery";
6
6
  import type { GetEscrowsFromIndexerResponse as Escrow } from "@trustless-work/escrow/types";
7
7
 
@@ -0,0 +1,8 @@
1
+ {
2
+ "dependencies": {
3
+ "recharts": "latest",
4
+ "@trustless-work/escrow": "latest"
5
+ },
6
+ "devDependencies": {},
7
+ "shadcnComponents": ["card", "separator", "chart", "empty"]
8
+ }
@@ -1,30 +1,16 @@
1
1
  {
2
2
  "dependencies": {
3
- "react": "^18.2.0",
4
- "react-dom": "^18.2.0",
5
- "react-hook-form": "^7.53.0",
6
- "zod": "^3.23.8",
7
- "@trustless-work/escrow": "^3.0.4",
8
- "@tanstack/react-query": "^5.75.0",
9
- "@tanstack/react-query-devtools": "^5.75.0",
10
- "tailwindcss": "^3.3.3",
11
- "tsup": "^8.3.5",
12
- "typescript": "^5.6.3",
13
- "@hookform/resolvers": "^3.10.0",
14
- "@creit-tech/stellar-wallets-kit": "^1.8.0",
15
- "axios": "^1.7.9",
16
- "@tanstack/react-table": "^8.21.3",
17
- "react-day-picker": "^9.5.0",
18
- "recharts": "^2.13.3"
3
+ "react-hook-form": "latest",
4
+ "zod": "latest",
5
+ "@trustless-work/escrow": "latest",
6
+ "@tanstack/react-query": "latest",
7
+ "@tanstack/react-query-devtools": "latest",
8
+ "@hookform/resolvers": "latest",
9
+ "@creit-tech/stellar-wallets-kit": "latest",
10
+ "axios": "latest",
11
+ "@tanstack/react-table": "latest",
12
+ "react-day-picker": "latest",
13
+ "recharts": "latest"
19
14
  },
20
- "devDependencies": {
21
- "postcss": "^8",
22
- "prettier": "^3.3.3",
23
- "tailwindcss": "^3.4.1",
24
- "typescript": "^5",
25
- "@types/next": "^8.0.7",
26
- "@types/node": "^20",
27
- "@types/react": "^18.3.23",
28
- "@types/react-dom": "^18"
29
- }
15
+ "devDependencies": {}
30
16
  }
@@ -0,0 +1,30 @@
1
+ {
2
+ "dependencies": {
3
+ "react-hook-form": "latest",
4
+ "@hookform/resolvers": "latest",
5
+ "zod": "latest",
6
+ "@trustless-work/escrow": "latest",
7
+ "@tanstack/react-table": "latest",
8
+ "react-day-picker": "latest"
9
+ },
10
+ "devDependencies": {},
11
+ "shadcnComponents": [
12
+ "button",
13
+ "input",
14
+ "form",
15
+ "card",
16
+ "select",
17
+ "textarea",
18
+ "dialog",
19
+ "table",
20
+ "calendar",
21
+ "popover",
22
+ "separator",
23
+ "badge",
24
+ "tabs",
25
+ "avatar",
26
+ "tooltip",
27
+ "checkbox",
28
+ "progress"
29
+ ]
30
+ }
@@ -14,7 +14,7 @@ import {
14
14
  GetEscrowsFromIndexerResponse as Escrow,
15
15
  Role,
16
16
  } from "@trustless-work/escrow/types";
17
- import { FundEscrowDialog } from "../../single-multi-release/fund-escrow/dialog/FundEscrow";
17
+ // import { FundEscrowDialog } from "../../single-multi-release/fund-escrow/dialog/FundEscrow";
18
18
 
19
19
  interface ActionsProps {
20
20
  selectedEscrow: Escrow;
@@ -28,49 +28,49 @@ export const roleActions: {
28
28
  icon: React.ReactNode;
29
29
  color: string;
30
30
  }[] = [
31
- {
32
- role: "signer",
33
- actions: ["fundEscrow"],
34
- icon: <Wallet className="h-6 w-6 text-primary" />,
35
- color: "",
36
- },
37
- {
38
- role: "approver",
39
- actions: ["fundEscrow", "approveMilestone", "startDispute"],
40
- icon: <CheckCircle className="h-6 w-6 text-primary" />,
41
- color: "0",
42
- },
43
- {
44
- role: "serviceProvider",
45
- actions: ["fundEscrow", "completeMilestone", "startDispute"],
46
- icon: <Briefcase className="h-6 w-6 text-primary" />,
47
- color: "0",
48
- },
49
- {
50
- role: "disputeResolver",
51
- actions: ["fundEscrow", "resolveDispute"],
52
- icon: <Scale className="h-6 w-6 text-primary" />,
53
- color: "00",
54
- },
55
- {
56
- role: "releaseSigner",
57
- actions: ["fundEscrow", "releasePayment"],
58
- icon: <Unlock className="h-6 w-6 text-primary" />,
59
- color: "",
60
- },
61
- {
62
- role: "platformAddress",
63
- actions: ["fundEscrow", "editEscrow"],
64
- icon: <Settings className="h-6 w-6 text-primary" />,
65
- color: "0",
66
- },
67
- {
68
- role: "receiver",
69
- actions: ["fundEscrow"],
70
- icon: <DollarSign className="h-6 w-6 text-primary" />,
71
- color: "",
72
- },
73
- ];
31
+ {
32
+ role: "signer",
33
+ actions: ["fundEscrow"],
34
+ icon: <Wallet className="h-6 w-6 text-primary" />,
35
+ color: "",
36
+ },
37
+ {
38
+ role: "approver",
39
+ actions: ["fundEscrow", "approveMilestone", "startDispute"],
40
+ icon: <CheckCircle className="h-6 w-6 text-primary" />,
41
+ color: "0",
42
+ },
43
+ {
44
+ role: "serviceProvider",
45
+ actions: ["fundEscrow", "completeMilestone", "startDispute"],
46
+ icon: <Briefcase className="h-6 w-6 text-primary" />,
47
+ color: "0",
48
+ },
49
+ {
50
+ role: "disputeResolver",
51
+ actions: ["fundEscrow", "resolveDispute"],
52
+ icon: <Scale className="h-6 w-6 text-primary" />,
53
+ color: "00",
54
+ },
55
+ {
56
+ role: "releaseSigner",
57
+ actions: ["fundEscrow", "releasePayment"],
58
+ icon: <Unlock className="h-6 w-6 text-primary" />,
59
+ color: "",
60
+ },
61
+ {
62
+ role: "platformAddress",
63
+ actions: ["fundEscrow", "editEscrow"],
64
+ icon: <Settings className="h-6 w-6 text-primary" />,
65
+ color: "0",
66
+ },
67
+ {
68
+ role: "receiver",
69
+ actions: ["fundEscrow"],
70
+ icon: <DollarSign className="h-6 w-6 text-primary" />,
71
+ color: "",
72
+ },
73
+ ];
74
74
 
75
75
  export const actionIcons: Record<string, React.ReactNode> = {
76
76
  fundEscrow: <DollarSign className="h-6 w-6 text-primary/60" />,
@@ -160,7 +160,8 @@ export const Actions = ({
160
160
  </div>
161
161
  )}
162
162
 
163
- <FundEscrowDialog />
163
+ {/* FundEscrow */}
164
+ {/* <FundEscrowDialog /> */}
164
165
  </div>
165
166
  );
166
167
  };
@@ -2,6 +2,7 @@
2
2
  import React from "react";
3
3
  import { Button } from "__UI_BASE__/button";
4
4
  import { Card, CardContent, CardHeader, CardTitle } from "__UI_BASE__/card";
5
+ import { Tooltip, TooltipContent, TooltipTrigger } from "__UI_BASE__/tooltip";
5
6
  import {
6
7
  FileCheck2,
7
8
  Eye,
@@ -17,8 +18,8 @@ import {
17
18
  SingleReleaseMilestone,
18
19
  } from "@trustless-work/escrow";
19
20
  import { Badge } from "__UI_BASE__/badge";
20
- import { ChangeMilestoneStatusDialog } from "../../single-multi-release/change-milestone-status/dialog/ChangeMilestoneStatus";
21
- import { ApproveMilestoneButton } from "../../single-multi-release/approve-milestone/button/ApproveMilestone";
21
+ // import { ChangeMilestoneStatusDialog } from "../../single-multi-release/change-milestone-status/dialog/ChangeMilestoneStatus";
22
+ // import { ApproveMilestoneButton } from "../../single-multi-release/approve-milestone/button/ApproveMilestone";
22
23
  import { formatCurrency } from "@/components/tw-blocks/helpers/format.helper";
23
24
 
24
25
  interface MilestoneCardProps {
@@ -107,10 +108,10 @@ const MilestoneCardComponent = ({
107
108
  !("flags" in milestone && milestone.flags?.approved)
108
109
  ) {
109
110
  buttons.push(
110
- <ChangeMilestoneStatusDialog
111
- key={`change-status-${milestoneIndex}`}
112
- milestoneIndex={milestoneIndex}
113
- />
111
+ // <ChangeMilestoneStatusDialog
112
+ // key={`change-status-${milestoneIndex}`}
113
+ // milestoneIndex={milestoneIndex}
114
+ // />
114
115
  );
115
116
  }
116
117
 
@@ -124,10 +125,10 @@ const MilestoneCardComponent = ({
124
125
  !milestone.flags?.resolved))
125
126
  ) {
126
127
  buttons.push(
127
- <ApproveMilestoneButton
128
- key={`approve-${milestoneIndex}`}
129
- milestoneIndex={milestoneIndex}
130
- />
128
+ // <ApproveMilestoneButton
129
+ // key={`approve-${milestoneIndex}`}
130
+ // milestoneIndex={milestoneIndex}
131
+ // />
131
132
  );
132
133
  }
133
134
 
@@ -190,11 +191,22 @@ const MilestoneCardComponent = ({
190
191
  className="hover:shadow-lg transition-all duration-200"
191
192
  >
192
193
  <CardHeader className="pb-4">
193
- <div className="flex items-center justify-between">
194
- <CardTitle className="text-base font-semibold text-foreground truncate">
195
- {milestone.description}
196
- </CardTitle>
197
- {getMilestoneStatusBadge(milestone)}
194
+ <div className="flex items-center justify-between gap-2 min-w-0">
195
+ <div className="min-w-0 flex-1 overflow-hidden">
196
+ <Tooltip>
197
+ <TooltipTrigger asChild>
198
+ <CardTitle className="text-base font-semibold text-foreground truncate block">
199
+ {milestone.description}
200
+ </CardTitle>
201
+ </TooltipTrigger>
202
+ <TooltipContent side="top" className="max-w-[min(20rem,90vw)]">
203
+ {milestone.description}
204
+ </TooltipContent>
205
+ </Tooltip>
206
+ </div>
207
+ <div className="flex-shrink-0">
208
+ {getMilestoneStatusBadge(milestone)}
209
+ </div>
198
210
  </div>
199
211
  </CardHeader>
200
212
 
@@ -178,7 +178,7 @@ export const MilestoneDetailDialog = ({
178
178
  <span className="font-bold text-foreground">
179
179
  {formatCurrency(
180
180
  selectedMilestone.milestone.amount,
181
- selectedEscrow?.trustline?.name ?? "USDC"
181
+ selectedEscrow?.trustline?.symbol ?? "USDC"
182
182
  )}
183
183
  </span>
184
184
  </div>
@@ -268,7 +268,7 @@ export const MilestoneDetailDialog = ({
268
268
  <p className="text-sm font-medium text-red-700 dark:text-red-300">
269
269
  <span className="font-bold">Disputed by:</span>{" "}
270
270
  {selectedMilestone.milestone.disputeStartedBy ===
271
- "serviceProvider"
271
+ "serviceProvider"
272
272
  ? "Service Provider"
273
273
  : "Approver"}
274
274
  </p>
@@ -35,7 +35,7 @@ export const SuccessReleaseDialog = ({
35
35
  const trustlessPercentage = 0.3;
36
36
  const receiverPercentage = 100 - (platformFee + trustlessPercentage);
37
37
 
38
- const currency = selectedEscrow?.trustline?.name ?? "";
38
+ const currency = selectedEscrow?.trustline?.symbol ?? "";
39
39
 
40
40
  const cards = useMemo<
41
41
  Array<{
@@ -3,7 +3,7 @@ import {
3
3
  GetEscrowsFromIndexerResponse as Escrow,
4
4
  MultiReleaseMilestone,
5
5
  } from "@trustless-work/escrow/types";
6
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
6
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
7
7
  import { useEscrowContext } from "@/components/tw-blocks/providers/EscrowProvider";
8
8
  import { useEscrowAmountContext } from "@/components/tw-blocks/providers/EscrowAmountProvider";
9
9
 
@@ -5,7 +5,7 @@ import { startOfDay, endOfDay, format } from "date-fns";
5
5
  import type { DateRange as DayPickerDateRange } from "react-day-picker";
6
6
  import { usePathname, useRouter, useSearchParams } from "next/navigation";
7
7
  import type { SortingState } from "@tanstack/react-table";
8
- import { useWalletContext } from "../../wallet-kit/WalletProvider";
8
+ import { useWalletContext } from "../../providers/WalletProvider";
9
9
  import { useEscrowsByRoleQuery } from "../../tanstack/useEscrowsByRoleQuery";
10
10
  import type { GetEscrowsFromIndexerByRoleParams } from "@trustless-work/escrow";
11
11
  import { GetEscrowsFromIndexerResponse as Escrow } from "@trustless-work/escrow/types";
@@ -5,7 +5,7 @@ import { startOfDay, endOfDay, format } from "date-fns";
5
5
  import type { DateRange as DayPickerDateRange } from "react-day-picker";
6
6
  import { usePathname, useRouter, useSearchParams } from "next/navigation";
7
7
  import type { SortingState } from "@tanstack/react-table";
8
- import { useWalletContext } from "../../wallet-kit/WalletProvider";
8
+ import { useWalletContext } from "../../providers/WalletProvider";
9
9
  import { useEscrowsBySignerQuery } from "../../tanstack/useEscrowsBySignerQuery";
10
10
  import { GetEscrowsFromIndexerResponse as Escrow } from "@trustless-work/escrow/types";
11
11
 
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { Button } from "__UI_BASE__/button";
3
3
  import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
4
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
4
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
5
5
  import {
6
6
  MultiReleaseStartDisputePayload,
7
7
  MultiReleaseMilestone,
@@ -16,7 +16,7 @@ import {
16
16
  ErrorResponse,
17
17
  handleError,
18
18
  } from "@/components/tw-blocks/handle-errors/handle";
19
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
19
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
20
20
 
21
21
  export function useDisputeMilestone({
22
22
  onSuccess,
@@ -8,7 +8,7 @@ import {
8
8
  InitializeMultiReleaseEscrowResponse,
9
9
  } from "@trustless-work/escrow/types";
10
10
  import { toast } from "sonner";
11
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
11
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
12
12
  import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
13
13
  import {
14
14
  ErrorResponse,
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { Button } from "__UI_BASE__/button";
3
3
  import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
4
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
4
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
5
5
  import {
6
6
  MultiReleaseReleaseFundsPayload,
7
7
  MultiReleaseMilestone,
@@ -16,7 +16,7 @@ import {
16
16
  ErrorResponse,
17
17
  handleError,
18
18
  } from "@/components/tw-blocks/handle-errors/handle";
19
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
19
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
20
20
  import { useEscrowDialogs } from "@/components/tw-blocks/providers/EscrowDialogsProvider";
21
21
  import { useEscrowAmountContext } from "@/components/tw-blocks/providers/EscrowAmountProvider";
22
22
 
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { Button } from "__UI_BASE__/button";
3
3
  import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
4
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
4
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
5
5
  import {
6
6
  MultiReleaseResolveDisputePayload,
7
7
  MultiReleaseMilestone,
@@ -13,7 +13,7 @@ import {
13
13
  ErrorResponse,
14
14
  handleError,
15
15
  } from "@/components/tw-blocks/handle-errors/handle";
16
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
16
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
17
17
 
18
18
  type DistributionInput = { address: string; amount: string | number };
19
19
 
@@ -10,7 +10,7 @@ import {
10
10
  } from "@trustless-work/escrow/types";
11
11
  import { toast } from "sonner";
12
12
  import { useEscrowContext } from "@/components/tw-blocks/providers/EscrowProvider";
13
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
13
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
14
14
  import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
15
15
  import {
16
16
  ErrorResponse,
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { Button } from "__UI_BASE__/button";
3
3
  import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
4
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
4
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
5
5
  import { WithdrawRemainingFundsPayload } from "@trustless-work/escrow/types";
6
6
  import { toast } from "sonner";
7
7
  import {
@@ -13,7 +13,7 @@ import {
13
13
  ErrorResponse,
14
14
  handleError,
15
15
  } from "@/components/tw-blocks/handle-errors/handle";
16
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
16
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
17
17
 
18
18
  type DistributionInput = { address: string; amount: string | number };
19
19
 
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { Button } from "__UI_BASE__/button";
3
3
  import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
4
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
4
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
5
5
  import {
6
6
  ApproveMilestonePayload,
7
7
  MultiReleaseMilestone,
@@ -13,7 +13,7 @@ import {
13
13
  ErrorResponse,
14
14
  handleError,
15
15
  } from "@/components/tw-blocks/handle-errors/handle";
16
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
16
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
17
17
 
18
18
  export function useApproveMilestone({
19
19
  onSuccess,
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { Button } from "__UI_BASE__/button";
3
3
  import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
4
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
4
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
5
5
  import { ChangeMilestoneStatusPayload } from "@trustless-work/escrow/types";
6
6
  import { toast } from "sonner";
7
7
  import {
@@ -13,7 +13,7 @@ import {
13
13
  ErrorResponse,
14
14
  handleError,
15
15
  } from "@/components/tw-blocks/handle-errors/handle";
16
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
16
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
17
17
 
18
18
  export function useChangeMilestoneStatus({
19
19
  onSuccess,
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { Button } from "__UI_BASE__/button";
3
3
  import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
4
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
4
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
5
5
  import { FundEscrowPayload } from "@trustless-work/escrow/types";
6
6
  import { toast } from "sonner";
7
7
  import {
@@ -10,7 +10,7 @@ import {
10
10
  ErrorResponse,
11
11
  handleError,
12
12
  } from "@/components/tw-blocks/handle-errors/handle";
13
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
13
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
14
14
 
15
15
  export function useFundEscrow({ onSuccess }: { onSuccess?: () => void } = {}) {
16
16
  const { fundEscrow } = useEscrowsMutations();
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { Button } from "__UI_BASE__/button";
3
3
  import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
4
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
4
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
5
5
  import { SingleReleaseStartDisputePayload } from "@trustless-work/escrow/types";
6
6
  import { toast } from "sonner";
7
7
  import {
@@ -8,7 +8,7 @@ import {
8
8
  InitializeSingleReleaseEscrowResponse,
9
9
  } from "@trustless-work/escrow/types";
10
10
  import { toast } from "sonner";
11
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
11
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
12
12
  import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
13
13
  import {
14
14
  ErrorResponse,
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { Button } from "__UI_BASE__/button";
3
3
  import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
4
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
4
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
5
5
  import { SingleReleaseReleaseFundsPayload } from "@trustless-work/escrow/types";
6
6
  import { toast } from "sonner";
7
7
  import {
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { Button } from "__UI_BASE__/button";
3
3
  import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
4
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
4
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
5
5
  import { SingleReleaseResolveDisputePayload } from "@trustless-work/escrow/types";
6
6
  import { toast } from "sonner";
7
7
  import {
@@ -10,7 +10,7 @@ import {
10
10
  ErrorResponse,
11
11
  handleError,
12
12
  } from "@/components/tw-blocks/handle-errors/handle";
13
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
13
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
14
14
 
15
15
  type DistributionInput = { address: string; amount: string | number };
16
16
 
@@ -13,7 +13,7 @@ import {
13
13
  } from "@trustless-work/escrow/types";
14
14
  import { toast } from "sonner";
15
15
  import { useEscrowContext } from "@/components/tw-blocks/providers/EscrowProvider";
16
- import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
16
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
17
17
  import { useEscrowsMutations } from "@/components/tw-blocks/tanstack/useEscrowsMutations";
18
18
  import {
19
19
  ErrorResponse,
@@ -0,0 +1,7 @@
1
+ {
2
+ "dependencies": {
3
+ "axios": "latest"
4
+ },
5
+ "devDependencies": {},
6
+ "shadcnComponents": []
7
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "dependencies": {},
3
+ "devDependencies": {},
4
+ "shadcnComponents": []
5
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dependencies": {
3
+ "@tanstack/react-query": "latest",
4
+ "@tanstack/react-query-devtools": "latest"
5
+ },
6
+ "devDependencies": {},
7
+ "shadcnComponents": []
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dependencies": {
3
+ "@tanstack/react-query": "latest",
4
+ "@trustless-work/escrow": "latest"
5
+ },
6
+ "devDependencies": {},
7
+ "shadcnComponents": []
8
+ }
@@ -2,7 +2,7 @@
2
2
 
3
3
  import * as React from "react";
4
4
  import { useWallet } from "./useWallet";
5
- import { useWalletContext } from "./WalletProvider";
5
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
6
6
  import { Button } from "__UI_BASE__/button";
7
7
  import { Popover, PopoverContent, PopoverTrigger } from "__UI_BASE__/popover";
8
8
  import { Check, Copy, LogOut, ChevronDown, Wallet } from "lucide-react";
@@ -0,0 +1,7 @@
1
+ {
2
+ "dependencies": {
3
+ "@creit-tech/stellar-wallets-kit": "latest"
4
+ },
5
+ "devDependencies": {},
6
+ "shadcnComponents": ["button", "popover"]
7
+ }
@@ -14,7 +14,7 @@ export const trustlines = [
14
14
  },
15
15
  {
16
16
  symbol: "EURC",
17
- address: "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
17
+ address: "GB3Q6QDZYTHWT7E5PVS3W7FUT5GVAFC5KSZFFLPU25GO7VTC3NM2ZTVO",
18
18
  network: "testnet",
19
19
  },
20
20
  // MAINNET
@@ -38,6 +38,6 @@ export const trustlineOptions = Array.from(
38
38
  .map((trustline) => [
39
39
  trustline.address,
40
40
  { value: trustline.address, label: trustline.symbol },
41
- ])
42
- ).values()
41
+ ]),
42
+ ).values(),
43
43
  );
@@ -3,7 +3,7 @@ import {
3
3
  disconnectWalletKit,
4
4
  getSelectedWallet,
5
5
  } from "./wallet-kit";
6
- import { useWalletContext } from "./WalletProvider";
6
+ import { useWalletContext } from "@/components/tw-blocks/providers/WalletProvider";
7
7
 
8
8
  /**
9
9
  * Custom hook that provides wallet connection and disconnection functionality