From fd35c7e94e98b517f36c83fa14fcf775bb6c345f Mon Sep 17 00:00:00 2001 From: Derek <256792747+decofe@users.noreply.github.com> Date: Wed, 30 Sep 2026 12:47:23 +0000 Subject: [PATCH 1/5] feat: default to OUSD on mainnet Co-authored-by: Derek Cofausper <256792747+decofe@users.noreply.github.com> --- package.json | 4 +-- pnpm-lock.yaml | 77 +++++++++++++++++++++---------------------- src/api.ts | 14 +++++--- src/chat.ts | 59 ++++++++++++++++++++++----------- src/lib/slack.ts | 1 + src/lib/tempo.test.ts | 16 +++++++++ src/lib/tempo.ts | 19 +++++++++-- src/lib/tip.ts | 47 ++++++++++++++++++++------ 8 files changed, 160 insertions(+), 77 deletions(-) diff --git a/package.json b/package.json index a8c0757..0fa8ba9 100644 --- a/package.json +++ b/package.json @@ -40,11 +40,11 @@ "hono": "4.13.7", "kysely": "0.28.17", "nanoid": "^5.1.16", - "ox": "0.14.20", + "ox": "0.14.45", "react": "19.2.5", "react-dom": "19.2.5", "tapimo": "0.5.2", - "viem": "^2.55.10", + "viem": "^2.57.1", "wagmi": "^3.6.14", "zod": "4.4.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b9bb2b9..c64de7b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -70,7 +70,7 @@ importers: version: 1.167.35(@tanstack/react-router@1.169.2(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@voidzero-dev/vite-plus-core@0.1.24) accounts: specifier: ^0.15.2 - version: 0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14) + version: 0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14) chat: specifier: 4.27.0 version: 4.27.0 @@ -84,8 +84,8 @@ importers: specifier: ^5.1.16 version: 5.1.16 ox: - specifier: 0.14.20 - version: 0.14.20(typescript@6.0.3)(zod@4.4.3) + specifier: 0.14.45 + version: 0.14.45(typescript@6.0.3)(zod@4.4.3) react: specifier: 19.2.5 version: 19.2.5 @@ -96,11 +96,11 @@ importers: specifier: 0.5.2 version: 0.5.2(0a9fca14114bb98809b2b223454df2b6) viem: - specifier: ^2.55.10 - version: 2.55.10(typescript@6.0.3)(zod@4.4.3) + specifier: ^2.57.1 + version: 2.57.1(typescript@6.0.3)(zod@4.4.3) wagmi: specifier: ^3.6.14 - version: 3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) + version: 3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) zod: specifier: 4.4.3 version: 4.4.3 @@ -4830,8 +4830,8 @@ packages: typescript: optional: true - ox@0.14.33: - resolution: {integrity: sha512-rooA/4o7bBof4Ge2VH/eovfNPb/AEEYyrNj03wggc55g5HZD8Pjs/OeWhttgjic3dDcqn0r29bDuvQEdTiUemQ==} + ox@0.14.45: + resolution: {integrity: sha512-jpsQ+p0JZh9mKCxxzxz0d5qFHZZg2/O9xW18IpEC/dNXXPVqmDJ0c//9RMz0CILkbSGPA42+cbU0fC/ghwJ03w==} peerDependencies: typescript: '>=5.4.0' peerDependenciesMeta: @@ -5930,8 +5930,8 @@ packages: typescript: optional: true - viem@2.55.10: - resolution: {integrity: sha512-Q9Ba+/ma81U2M5o5P2AQ7Ux8rTIwmCZvUcr8rKdQ22bV0IBFHllM2m5gWDP8hFaUN2nH2oW3QG44amRazflYNQ==} + viem@2.57.1: + resolution: {integrity: sha512-eOV3fHnaMzkIFRefZg1icWztAKvBHg7RMKEH89ywY7hnyq1VxI4s/osXnTBViOsEZ7/LbbxU3w+JaIrbeIXRPQ==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -8782,23 +8782,23 @@ snapshots: dependencies: vue: 3.5.40(typescript@6.0.3) - '@wagmi/connectors@8.0.13(@wagmi/core@3.4.11)(accounts@0.15.2)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3))': + '@wagmi/connectors@8.0.13(@wagmi/core@3.4.11)(accounts@0.15.2)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3))': dependencies: - '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) - viem: 2.55.10(typescript@6.0.3)(zod@4.4.3) + '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) + viem: 2.57.1(typescript@6.0.3)(zod@4.4.3) optionalDependencies: - accounts: 0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14) + accounts: 0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14) typescript: 6.0.3 - '@wagmi/core@3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3))': + '@wagmi/core@3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3))': dependencies: eventemitter3: 5.0.1 mipd: 0.0.7(typescript@6.0.3) - viem: 2.55.10(typescript@6.0.3)(zod@4.4.3) + viem: 2.57.1(typescript@6.0.3)(zod@4.4.3) zustand: 5.0.0(@types/react@19.2.14)(react@19.2.5)(use-sync-external-store@1.4.0(react@19.2.5)) optionalDependencies: '@tanstack/query-core': 5.100.10 - accounts: 0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14) + accounts: 0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14) typescript: 6.0.3 transitivePeerDependencies: - '@types/react' @@ -8834,16 +8834,16 @@ snapshots: jose: 6.2.3 mipd: 0.0.7(typescript@6.0.3) mppx: 0.8.9(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(express@5.2.1)(hono@4.13.7)(typescript@6.0.3)(viem@2.54.6(typescript@6.0.3)(zod@4.4.3)) - ox: 0.14.33(typescript@6.0.3)(zod@4.4.3) + ox: 0.14.45(typescript@6.0.3)(zod@4.4.3) wata: 0.4.0(react@19.2.5)(typescript@6.0.3) webauthx: 0.1.2(typescript@6.0.3)(zod@4.4.3) zod: 4.4.3 zustand: 5.0.13(@types/react@19.2.14)(react@19.2.5)(use-sync-external-store@1.4.0(react@19.2.5)) optionalDependencies: - '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) + '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) react: 19.2.5 viem: 2.54.6(typescript@6.0.3)(zod@4.4.3) - wagmi: 3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) + wagmi: 3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) transitivePeerDependencies: - '@modelcontextprotocol/sdk' - '@types/react' @@ -8854,23 +8854,23 @@ snapshots: - typescript - use-sync-external-store - accounts@0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14): + accounts@0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14): dependencies: hono: 4.13.7 idb-keyval: 6.2.2 jose: 6.2.3 mipd: 0.0.7(typescript@6.0.3) - mppx: 0.8.9(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(express@5.2.1)(hono@4.13.7)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) - ox: 0.14.33(typescript@6.0.3)(zod@4.4.3) + mppx: 0.8.9(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(express@5.2.1)(hono@4.13.7)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) + ox: 0.14.45(typescript@6.0.3)(zod@4.4.3) wata: 0.4.0(react@19.2.5)(typescript@6.0.3) webauthx: 0.1.2(typescript@6.0.3)(zod@4.4.3) zod: 4.4.3 zustand: 5.0.13(@types/react@19.2.14)(react@19.2.5)(use-sync-external-store@1.4.0(react@19.2.5)) optionalDependencies: - '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) + '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) react: 19.2.5 - viem: 2.55.10(typescript@6.0.3)(zod@4.4.3) - wagmi: 3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) + viem: 2.57.1(typescript@6.0.3)(zod@4.4.3) + wagmi: 3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) transitivePeerDependencies: - '@modelcontextprotocol/sdk' - '@types/react' @@ -10902,13 +10902,13 @@ snapshots: transitivePeerDependencies: - typescript - mppx@0.8.9(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(express@5.2.1)(hono@4.13.7)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)): + mppx@0.8.9(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(express@5.2.1)(hono@4.13.7)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)): dependencies: '@stripe/stripe-js': 9.9.0 eventsource-parser: 3.1.0 incur: 0.4.19 ox: 0.14.30(typescript@6.0.3)(zod@4.4.3) - viem: 2.55.10(typescript@6.0.3)(zod@4.4.3) + viem: 2.57.1(typescript@6.0.3)(zod@4.4.3) zod: 4.4.3 optionalDependencies: '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3) @@ -11034,7 +11034,7 @@ snapshots: '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.2.3(typescript@6.0.3)(zod@4.4.3) + abitype: 1.3.0(typescript@6.0.3)(zod@4.4.3) eventemitter3: 5.0.1 optionalDependencies: typescript: 6.0.3 @@ -11056,7 +11056,7 @@ snapshots: transitivePeerDependencies: - zod - ox@0.14.33(typescript@6.0.3)(zod@4.4.3): + ox@0.14.45(typescript@6.0.3)(zod@4.4.3): dependencies: '@adraffy/ens-normalize': 1.11.1 '@noble/ciphers': 1.3.0 @@ -11064,7 +11064,7 @@ snapshots: '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.2.3(typescript@6.0.3)(zod@4.4.3) + abitype: 1.3.0(typescript@6.0.3)(zod@4.4.3) eventemitter3: 5.0.1 optionalDependencies: typescript: 6.0.3 @@ -12187,7 +12187,7 @@ snapshots: abitype: 1.3.0(typescript@6.0.3)(zod@4.4.3) kysely: 0.28.17 mitt: 3.0.1 - ox: 0.14.30(typescript@6.0.3)(zod@4.4.3) + ox: 0.14.20(typescript@6.0.3)(zod@4.4.3) zod: 4.4.3 transitivePeerDependencies: - typescript @@ -12515,7 +12515,7 @@ snapshots: - utf-8-validate - zod - viem@2.55.10(typescript@6.0.3)(zod@4.4.3): + viem@2.57.1(typescript@6.0.3)(zod@4.4.3): dependencies: '@noble/curves': 1.9.1 '@noble/hashes': 1.8.0 @@ -12523,7 +12523,7 @@ snapshots: '@scure/bip39': 1.6.0 abitype: 1.2.3(typescript@6.0.3)(zod@4.4.3) isows: 1.0.7(ws@8.21.0) - ox: 0.14.33(typescript@6.0.3)(zod@4.4.3) + ox: 0.14.45(typescript@6.0.3)(zod@4.4.3) ws: 8.21.0 optionalDependencies: typescript: 6.0.3 @@ -12736,14 +12736,14 @@ snapshots: w3c-keyname@2.2.8: {} - wagmi@3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)): + wagmi@3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)): dependencies: '@tanstack/react-query': 5.100.10(react@19.2.5) - '@wagmi/connectors': 8.0.13(@wagmi/core@3.4.11)(accounts@0.15.2)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) - '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) + '@wagmi/connectors': 8.0.13(@wagmi/core@3.4.11)(accounts@0.15.2)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) + '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) react: 19.2.5 use-sync-external-store: 1.4.0(react@19.2.5) - viem: 2.55.10(typescript@6.0.3)(zod@4.4.3) + viem: 2.57.1(typescript@6.0.3)(zod@4.4.3) optionalDependencies: typescript: 6.0.3 transitivePeerDependencies: @@ -12954,7 +12954,6 @@ time: chat@4.27.0: '2026-04-30T20:46:13.887Z' emulate@0.5.0: '2026-04-29T05:49:35.977Z' kysely@0.28.17: '2026-05-03T01:05:34.179Z' - ox@0.14.20: '2026-04-21T20:34:36.837Z' react-dom@19.2.5: '2026-04-08T18:39:31.423Z' react@19.2.5: '2026-04-08T18:39:24.455Z' tailwindcss@4.2.4: '2026-04-21T13:15:55.494Z' diff --git a/src/api.ts b/src/api.ts index ff9eb06..a1bc79a 100644 --- a/src/api.ts +++ b/src/api.ts @@ -115,7 +115,9 @@ export const api = new Hono<{ chainName: Tempo.getChainName(link.chain_id), expiresAt: link.expires_at, ok: true as const, - tokenAddress: Address.checksum(link.default_token_address ?? Tempo.addressLookup.pathUsd), + tokenAddress: Address.checksum( + link.default_token_address ?? Tempo.getDefaultTokenAddress(link.chain_id), + ), }) }) .post( @@ -176,7 +178,9 @@ export const api = new Hono<{ expiresAt: link.access_key_expires_at, keyAuthorization: body.keyAuthorization, rootAddress: body.address, - tokenAddress: Address.checksum(link.default_token_address ?? Tempo.addressLookup.pathUsd), + tokenAddress: Address.checksum( + link.default_token_address ?? Tempo.getDefaultTokenAddress(link.chain_id), + ), }) const now = new Date().toISOString() const existingAccount = await c.var.db @@ -252,7 +256,9 @@ export const api = new Hono<{ .where( 'token_address', '=', - Address.checksum(link.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum( + link.default_token_address ?? Tempo.getDefaultTokenAddress(link.chain_id), + ), ) .execute() await c.var.db @@ -274,7 +280,7 @@ export const api = new Hono<{ id: Nanoid.generate(), revoked_at: null, token_address: Address.checksum( - link.default_token_address ?? Tempo.addressLookup.pathUsd, + link.default_token_address ?? Tempo.getDefaultTokenAddress(link.chain_id), ), updated_at: now, }) diff --git a/src/chat.ts b/src/chat.ts index 34a5209..580279d 100644 --- a/src/chat.ts +++ b/src/chat.ts @@ -832,7 +832,8 @@ const actions = { } const reactionTipConfigs = await getReactionTipConfigs(DB.create(env.DB), workspace.id) - const tokenAddress = workspace.default_token_address ?? Tempo.addressLookup.pathUsd + const tokenAddress = + workspace.default_token_address ?? Tempo.getDefaultTokenAddress(workspace.chain_id) const tokenOptions = workspaceTokenOptions(workspace.chain_id) const tokenValue = tokenOptions.find((option) => option.address.toLowerCase() === tokenAddress.toLowerCase()) @@ -1014,7 +1015,7 @@ const modalSubmits = { if (!creator) return const tokenAddress = Address.checksum( - workspace.default_token_address ?? Tempo.addressLookup.pathUsd, + workspace.default_token_address ?? Tempo.getDefaultTokenAddress(workspace.chain_id), ) const balance = await Actions.token.getBalance( createClient({ @@ -1167,7 +1168,8 @@ const modalSubmits = { if (!installation) return const now = new Date() - const tokenAddress = workspace.default_token_address ?? Tempo.addressLookup.pathUsd + const tokenAddress = + workspace.default_token_address ?? Tempo.getDefaultTokenAddress(workspace.chain_id) const tipRaffle = { chain_id: workspace.chain_id, created_at: now.toISOString(), @@ -1375,7 +1377,8 @@ const handlers = { return } - const tokenAddress = workspace.default_token_address ?? Tempo.addressLookup.pathUsd + const tokenAddress = + workspace.default_token_address ?? Tempo.getDefaultTokenAddress(workspace.chain_id) const token = await Tapimo.getTokenMetadata(env, workspace.chain_id, tokenAddress) if (!('openModal' in event)) { await postPrivateReply( @@ -1451,7 +1454,8 @@ const handlers = { return } - const tokenAddress = workspace.default_token_address ?? Tempo.addressLookup.pathUsd + const tokenAddress = + workspace.default_token_address ?? Tempo.getDefaultTokenAddress(workspace.chain_id) const token = await Tapimo.getTokenMetadata(env, workspace.chain_id, tokenAddress) if (!('openModal' in event)) return await event.openModal( @@ -1579,7 +1583,8 @@ const handlers = { provider_id: ctx.provider.id, provider_message_ts: 'pending', requester_member_id: requester.memberId, - token_address: workspace.default_token_address ?? Tempo.addressLookup.pathUsd, + token_address: + workspace.default_token_address ?? Tempo.getDefaultTokenAddress(workspace.chain_id), updated_at: now, workspace_id: workspace.id, } satisfies DB_gen.Insertable.tip_ask @@ -2590,6 +2595,7 @@ const tipRaffleDurationOptions = [ { label: '7 days', ms: 7 * 24 * 60 * 60 * 1000, value: '7d' }, // 7 days ] as const const tokenOptions = [ + { address: Tempo.addressLookup.ousd, label: 'OUSD', value: 'OUSD' }, { address: Tempo.addressLookup.pathUsd, label: 'PathUSD', value: 'pathUSD' }, { address: Tempo.addressLookup.usdcE, label: 'USDC.e', value: 'USDC.e' }, { address: Tempo.addressLookup.usdt0, label: 'USDT0', value: 'USDT0' }, @@ -4608,7 +4614,9 @@ async function sendTipRaffleEscrowPayout( feePayer: 'sender', isDefaultToken: Address.isEqual( Address.checksum(existing.token_address), - Address.checksum(existing.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum( + existing.default_token_address ?? Tempo.getDefaultTokenAddress(existing.chain_id), + ), ), memo: existing.memo, ok: true, @@ -4745,7 +4753,9 @@ async function sendTipRaffleEscrowPayout( feePayer: 'sender', isDefaultToken: Address.isEqual( Address.checksum(input.tokenAddress), - Address.checksum(workspace.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum( + workspace.default_token_address ?? Tempo.getDefaultTokenAddress(workspace.chain_id), + ), ), memo: input.memo, ok: true, @@ -4890,7 +4900,10 @@ async function tipRaffleMessage(db: DB.Type, tipRaffle: TipRaffleMessageInput) { const value = formatAmount(amount) return Address.isEqual( Address.checksum(tipRaffle.token_address), - Address.checksum(tipRaffle.workspace_default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum( + tipRaffle.workspace_default_token_address ?? + Tempo.getDefaultTokenAddress(tipRaffle.chain_id), + ), ) ? formatCurrencyAmount(value, token.currency) : formatTipAmount(value, token.currency, token.symbol) @@ -4997,7 +5010,9 @@ async function tipAskMessage(db: DB.Type, tipAsk: TipAskMessageInput) { const value = formatAmount(amount) return Address.isEqual( Address.checksum(tipAsk.token_address), - Address.checksum(tipAsk.workspace_default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum( + tipAsk.workspace_default_token_address ?? Tempo.getDefaultTokenAddress(tipAsk.chain_id), + ), ) ? formatCurrencyAmount(value, token.currency) : formatTipAmount(value, token.currency, token.symbol) @@ -5312,7 +5327,7 @@ export async function updateReceiptBoostAggregate( const amount = formatAmount(group.amount) const displayAmount = Address.isEqual( Address.checksum(group.tokenAddress), - Address.checksum(group.defaultTokenAddress ?? Tempo.addressLookup.pathUsd), + Address.checksum(group.defaultTokenAddress ?? Tempo.getDefaultTokenAddress(group.chainId)), ) ? formatCurrencyAmount(amount, token.currency) : formatTipAmount(amount, token.currency, token.symbol) @@ -6056,7 +6071,9 @@ async function postConnectLink(event: TipEvent, ctx: HandlerContext) { (row) => !row.token_address || row.token_address.toLowerCase() === - (workspace.default_token_address ?? Tempo.addressLookup.pathUsd).toLowerCase(), + ( + workspace.default_token_address ?? Tempo.getDefaultTokenAddress(workspace.chain_id) + ).toLowerCase(), ) if (accessKey && !ctx.forceConnectRefresh) { await postPrivateReply(event, event.user, 'Already connected', { threadTs: ctx.threadTs }) @@ -6801,7 +6818,7 @@ async function reactionTipAggregateText( const amount = formatAmount(row.amount) const displayAmount = Address.isEqual( Address.checksum(row.token_address), - Address.checksum(row.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum(row.default_token_address ?? Tempo.getDefaultTokenAddress(row.chain_id)), ) ? formatCurrencyAmount(amount, token.currency) : formatTipAmount(amount, token.currency, token.symbol) @@ -6819,7 +6836,7 @@ async function reactionTipAggregateText( const amount = formatAmount(row.amount) const displayAmount = Address.isEqual( Address.checksum(row.token_address), - Address.checksum(row.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum(row.default_token_address ?? Tempo.getDefaultTokenAddress(row.chain_id)), ) ? formatCurrencyAmount(amount, token.currency) : formatTipAmount(amount, token.currency, token.symbol) @@ -6844,7 +6861,7 @@ async function reactionTipAggregateText( const amount = formatAmount(row.amount) const displayAmount = Address.isEqual( Address.checksum(row.token_address), - Address.checksum(row.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum(row.default_token_address ?? Tempo.getDefaultTokenAddress(row.chain_id)), ) ? formatCurrencyAmount(amount, token.currency) : formatTipAmount(amount, token.currency, token.symbol) @@ -7036,7 +7053,9 @@ export async function updateSlackPendingTipMessage(db: DB.Type, result: Tip.Pend .executeTakeFirst() const amount = Address.isEqual( Address.checksum(result.pendingTip.token_address), - Address.checksum(workspace?.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum( + workspace?.default_token_address ?? Tempo.getDefaultTokenAddress(result.pendingTip.chain_id), + ), ) ? formatCurrencyAmount(formatAmount(result.pendingTip.amount), tokenMetadata.currency) : formatTipAmount( @@ -7320,7 +7339,8 @@ async function configCard( options?: { canEdit?: boolean; updated?: boolean }, ) { const reactionTipConfigs = await getReactionTipConfigs(db, workspace.id) - const tokenAddress = workspace.default_token_address ?? Tempo.addressLookup.pathUsd + const tokenAddress = + workspace.default_token_address ?? Tempo.getDefaultTokenAddress(workspace.chain_id) const token = Tempo.getTokenMetadataFallback(tokenAddress) const networkLabel = workspace.chain_id === Tempo.chainLookup.mainnet ? 'Mainnet' : 'Testnet' return { @@ -7429,7 +7449,8 @@ function configFallbackText( reactionTipConfigs: ReactionTipConfig[], options?: { updated?: boolean }, ) { - const tokenAddress = workspace.default_token_address ?? Tempo.addressLookup.pathUsd + const tokenAddress = + workspace.default_token_address ?? Tempo.getDefaultTokenAddress(workspace.chain_id) return `Setting Value\nNetwork ${configNetworkLabel(workspace)}\nDefault token ${configToken(workspace).symbol} ${Tempo.explorerLink(workspace.chain_id, tokenAddress)}\nDefault amount ${formatAmount(workspace.default_amount)}\nReaction tips ${reactionTipConfigsText(reactionTipConfigs)}${options?.updated ? '\nWorkspace settings updated' : ''}` } @@ -7439,7 +7460,7 @@ function configNetworkLabel(workspace: DB_gen.Selectable.workspace) { function configToken(workspace: DB_gen.Selectable.workspace) { return Tempo.getTokenMetadataFallback( - workspace.default_token_address ?? Tempo.addressLookup.pathUsd, + workspace.default_token_address ?? Tempo.getDefaultTokenAddress(workspace.chain_id), ) } diff --git a/src/lib/slack.ts b/src/lib/slack.ts index 5f5f3be..382158e 100644 --- a/src/lib/slack.ts +++ b/src/lib/slack.ts @@ -616,6 +616,7 @@ async function buildHomeView(input: { (async () => { // Fetch balances for every token allowed in this workspace, falling back to RPC. const tokens = [ + { address: Tempo.addressLookup.ousd, label: 'OUSD' }, { address: Tempo.addressLookup.pathUsd, label: 'PathUSD' }, { address: Tempo.addressLookup.usdcE, label: 'USDC.e' }, { address: Tempo.addressLookup.usdt0, label: 'USDT0' }, diff --git a/src/lib/tempo.test.ts b/src/lib/tempo.test.ts index e9ec5ca..a92aa2c 100644 --- a/src/lib/tempo.test.ts +++ b/src/lib/tempo.test.ts @@ -25,11 +25,20 @@ test('returns optional RPC URLs by chain', () => { expect(Tempo.getRpcUrl({}, 1)).toBe(undefined) }) +test('returns default token by chain', () => { + expect(Tempo.addressLookup.ousd).toBe('0x20c0000000000000000000006a37DA5C996874BE') + expect(Tempo.getDefaultTokenAddress(Tempo.chainLookup.mainnet)).toBe(Tempo.addressLookup.ousd) + expect(Tempo.getDefaultTokenAddress(Tempo.chainLookup.testnet)).toBe(Tempo.addressLookup.pathUsd) + expect(Tempo.getDefaultTokenAddress(Tempo.chainLookup.localnet)).toBe(Tempo.addressLookup.pathUsd) +}) + test('checks allowed tokens by chain', () => { + expect(Tempo.isAllowedToken(Tempo.chainLookup.mainnet, Tempo.addressLookup.ousd)).toBe(true) expect(Tempo.isAllowedToken(Tempo.chainLookup.mainnet, Tempo.addressLookup.pathUsd)).toBe(true) expect(Tempo.isAllowedToken(Tempo.chainLookup.mainnet, Tempo.addressLookup.usdcE)).toBe(true) expect(Tempo.isAllowedToken(Tempo.chainLookup.mainnet, Tempo.addressLookup.usdt0)).toBe(true) expect(Tempo.isAllowedToken(Tempo.chainLookup.mainnet, Tempo.addressLookup.alphaUsd)).toBe(false) + expect(Tempo.isAllowedToken(Tempo.chainLookup.testnet, Tempo.addressLookup.ousd)).toBe(false) expect(Tempo.isAllowedToken(Tempo.chainLookup.testnet, Tempo.addressLookup.pathUsd)).toBe(true) expect(Tempo.isAllowedToken(Tempo.chainLookup.testnet, Tempo.addressLookup.alphaUsd)).toBe(true) expect(Tempo.isAllowedToken(Tempo.chainLookup.testnet, Tempo.addressLookup.betaUsd)).toBe(true) @@ -39,6 +48,9 @@ test('checks allowed tokens by chain', () => { }) test('resolves supported token aliases', () => { + expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'OUSD')).toBe(Tempo.addressLookup.ousd) + expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'OpenUSD')).toBe(Tempo.addressLookup.ousd) + expect(Tempo.getTokenAddress(Tempo.chainLookup.testnet, 'ousd')).toBe(null) expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'USDC.e')).toBe(Tempo.addressLookup.usdcE) expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'usdc')).toBe(Tempo.addressLookup.usdcE) expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'USDT')).toBe(Tempo.addressLookup.usdt0) @@ -47,6 +59,10 @@ test('resolves supported token aliases', () => { }) test('formats Tempo token symbols and transaction links', () => { + expect(Tempo.getTokenMetadataFallback(Tempo.addressLookup.ousd)).toEqual({ + currency: 'USD', + symbol: 'OUSD', + }) expect(Tempo.getTokenMetadataFallback(Tempo.addressLookup.pathUsd)).toEqual({ currency: 'USD', symbol: 'PathUSD', diff --git a/src/lib/tempo.ts b/src/lib/tempo.ts index 8269263..8e5bd53 100644 --- a/src/lib/tempo.ts +++ b/src/lib/tempo.ts @@ -1,9 +1,11 @@ import { Address } from 'ox' import { tempo, tempoLocalnet, tempoModerato } from 'viem/tempo/chains' +import { ousd } from 'viem/tokens' export const addressLookup = { alphaUsd: Address.checksum('0x20c0000000000000000000000000000000000001'), betaUsd: Address.checksum('0x20c0000000000000000000000000000000000002'), + ousd: Address.checksum(ousd.addresses[tempo.id]), pathUsd: Address.checksum('0x20c0000000000000000000000000000000000000'), thetaUsd: Address.checksum('0x20c0000000000000000000000000000000000003'), usdcE: Address.checksum('0x20C000000000000000000000b9537d11c60E8b50'), @@ -23,6 +25,11 @@ export function getChain(chainId: number) { throw new Error(`Unsupported Tempo chain ${chainId}.`) } +export function getDefaultTokenAddress(chainId: number) { + if (chainId === chainLookup.mainnet) return addressLookup.ousd + return addressLookup.pathUsd +} + export function getRpcUrl( env: Pick, chainId: number, @@ -63,9 +70,12 @@ export function explorerLink(chainId: number, address: string) { export function isAllowedToken(chainId: number, tokenAddress: string) { const token = Address.checksum(tokenAddress) if (chainId === chainLookup.mainnet) - return [addressLookup.pathUsd, addressLookup.usdcE, addressLookup.usdt0].some((allowed) => - Address.isEqual(token, allowed), - ) + return [ + addressLookup.ousd, + addressLookup.pathUsd, + addressLookup.usdcE, + addressLookup.usdt0, + ].some((allowed) => Address.isEqual(token, allowed)) if (chainId === chainLookup.testnet || chainId === chainLookup.localnet) return [ addressLookup.pathUsd, @@ -82,6 +92,7 @@ export function getTokenAddress(chainId: number, value: string) { const normalized = value.toLowerCase().replace(/[.\-_\s]/g, '') const tokenAddress = (() => { + if (normalized === 'ousd' || normalized === 'openusd') return addressLookup.ousd if (normalized === 'pathusd' || normalized === 'path' || normalized === 'usd') return addressLookup.pathUsd if (normalized === 'usdce' || normalized === 'usdc') return addressLookup.usdcE @@ -96,6 +107,8 @@ export function getTokenAddress(chainId: number, value: string) { } export function getTokenMetadataFallback(tokenAddress: string) { + if (Address.isEqual(Address.checksum(tokenAddress), addressLookup.ousd)) + return { currency: 'USD', symbol: 'OUSD' } if (Address.isEqual(Address.checksum(tokenAddress), addressLookup.pathUsd)) return { currency: 'USD', symbol: 'PathUSD' } if (Address.isEqual(Address.checksum(tokenAddress), addressLookup.alphaUsd)) diff --git a/src/lib/tip.ts b/src/lib/tip.ts index cd1bda2..c3c79e2 100644 --- a/src/lib/tip.ts +++ b/src/lib/tip.ts @@ -233,7 +233,9 @@ export async function handleTipRequest( const amount = input.amount ?? executionWorkspace.default_amount const tokenAddress = Address.checksum( - input.tokenAddress ?? executionWorkspace.default_token_address ?? Tempo.addressLookup.pathUsd, + input.tokenAddress ?? + executionWorkspace.default_token_address ?? + Tempo.getDefaultTokenAddress(executionWorkspace.chain_id), ) if (!Tempo.isAllowedToken(executionWorkspace.chain_id, tokenAddress)) return { @@ -431,7 +433,9 @@ export async function handleTipBatchRequest( if (!Number.isSafeInteger(authorizedTotalAmount) || authorizedTotalAmount <= 0) return { code: 'failed', message: 'Payment amount is too large.', ok: false } const tokenAddress = Address.checksum( - input.tokenAddress ?? executionWorkspace.default_token_address ?? Tempo.addressLookup.pathUsd, + input.tokenAddress ?? + executionWorkspace.default_token_address ?? + Tempo.getDefaultTokenAddress(executionWorkspace.chain_id), ) if (!Tempo.isAllowedToken(executionWorkspace.chain_id, tokenAddress)) return { @@ -547,7 +551,10 @@ export async function handleTipBatchRequest( chainId: executionWorkspace.chain_id, isDefaultToken: Address.isEqual( Address.checksum(tokenAddress), - Address.checksum(executionWorkspace.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum( + executionWorkspace.default_token_address ?? + Tempo.getDefaultTokenAddress(executionWorkspace.chain_id), + ), ), memo: input.memo, ok: true, @@ -1373,7 +1380,10 @@ async function createPendingTip( chainId: input.workspace.chain_id, isDefaultToken: Address.isEqual( Address.checksum(input.tokenAddress), - Address.checksum(input.workspace.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum( + input.workspace.default_token_address ?? + Tempo.getDefaultTokenAddress(input.workspace.chain_id), + ), ), memo: input.memo, ok: true, @@ -1418,7 +1428,10 @@ async function createQueuedBatchTips( recipientProviderUserId: recipient.recipientProviderUserId, senderProviderUserId: input.senderProviderUserId, }, - Address.checksum(input.workspace.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum( + input.workspace.default_token_address ?? + Tempo.getDefaultTokenAddress(input.workspace.chain_id), + ), ) const result = existing ?? @@ -1594,7 +1607,9 @@ async function getSentPendingTipResult( chainId: pendingTip.chain_id, isDefaultToken: Address.isEqual( Address.checksum(pendingTip.token_address), - Address.checksum(tip.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum( + tip.default_token_address ?? Tempo.getDefaultTokenAddress(pendingTip.chain_id), + ), ), memo: pendingTip.memo, ok: true, @@ -2086,7 +2101,10 @@ async function submitTipBatch( feePayer, isDefaultToken: Address.isEqual( Address.checksum(input.tokenAddress), - Address.checksum(input.workspace.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum( + input.workspace.default_token_address ?? + Tempo.getDefaultTokenAddress(input.workspace.chain_id), + ), ), memo: input.memo, ok: true, @@ -2208,7 +2226,10 @@ async function submitSignedTipBatch( idempotencyKey: input.idempotencyKey, senderProviderUserId: input.payload.senderProviderUserId, }, - Address.checksum(input.workspace.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum( + input.workspace.default_token_address ?? + Tempo.getDefaultTokenAddress(input.workspace.chain_id), + ), ) if (existing) return existing @@ -2343,7 +2364,10 @@ async function submitSignedTipBatch( feePayer: 'sender', isDefaultToken: Address.isEqual( Address.checksum(input.tokenAddress), - Address.checksum(input.workspace.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum( + input.workspace.default_token_address ?? + Tempo.getDefaultTokenAddress(input.workspace.chain_id), + ), ), memo: input.memo, ok: true, @@ -2516,7 +2540,10 @@ async function submitSignedTip( feePayer: 'sender', isDefaultToken: Address.isEqual( Address.checksum(input.tokenAddress), - Address.checksum(input.workspace.default_token_address ?? Tempo.addressLookup.pathUsd), + Address.checksum( + input.workspace.default_token_address ?? + Tempo.getDefaultTokenAddress(input.workspace.chain_id), + ), ), memo: input.memo, ok: true, From d856d8a3ff8c1372b1c725efa1caa1fb2302146e Mon Sep 17 00:00:00 2001 From: Derek <256792747+decofe@users.noreply.github.com> Date: Wed, 30 Sep 2026 13:22:56 +0000 Subject: [PATCH 2/5] feat: default to OUSD on testnet Co-authored-by: Derek Cofausper <256792747+decofe@users.noreply.github.com> --- package.json | 4 +-- pnpm-lock.yaml | 77 ++++++++++++++++++++-------------------- src/chat.workers.test.ts | 2 +- src/lib/tempo.test.ts | 8 +++-- src/lib/tempo.ts | 15 +++++--- 5 files changed, 58 insertions(+), 48 deletions(-) diff --git a/package.json b/package.json index 0fa8ba9..a8c0757 100644 --- a/package.json +++ b/package.json @@ -40,11 +40,11 @@ "hono": "4.13.7", "kysely": "0.28.17", "nanoid": "^5.1.16", - "ox": "0.14.45", + "ox": "0.14.20", "react": "19.2.5", "react-dom": "19.2.5", "tapimo": "0.5.2", - "viem": "^2.57.1", + "viem": "^2.55.10", "wagmi": "^3.6.14", "zod": "4.4.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c64de7b..b9bb2b9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -70,7 +70,7 @@ importers: version: 1.167.35(@tanstack/react-router@1.169.2(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@voidzero-dev/vite-plus-core@0.1.24) accounts: specifier: ^0.15.2 - version: 0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14) + version: 0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14) chat: specifier: 4.27.0 version: 4.27.0 @@ -84,8 +84,8 @@ importers: specifier: ^5.1.16 version: 5.1.16 ox: - specifier: 0.14.45 - version: 0.14.45(typescript@6.0.3)(zod@4.4.3) + specifier: 0.14.20 + version: 0.14.20(typescript@6.0.3)(zod@4.4.3) react: specifier: 19.2.5 version: 19.2.5 @@ -96,11 +96,11 @@ importers: specifier: 0.5.2 version: 0.5.2(0a9fca14114bb98809b2b223454df2b6) viem: - specifier: ^2.57.1 - version: 2.57.1(typescript@6.0.3)(zod@4.4.3) + specifier: ^2.55.10 + version: 2.55.10(typescript@6.0.3)(zod@4.4.3) wagmi: specifier: ^3.6.14 - version: 3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) + version: 3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) zod: specifier: 4.4.3 version: 4.4.3 @@ -4830,8 +4830,8 @@ packages: typescript: optional: true - ox@0.14.45: - resolution: {integrity: sha512-jpsQ+p0JZh9mKCxxzxz0d5qFHZZg2/O9xW18IpEC/dNXXPVqmDJ0c//9RMz0CILkbSGPA42+cbU0fC/ghwJ03w==} + ox@0.14.33: + resolution: {integrity: sha512-rooA/4o7bBof4Ge2VH/eovfNPb/AEEYyrNj03wggc55g5HZD8Pjs/OeWhttgjic3dDcqn0r29bDuvQEdTiUemQ==} peerDependencies: typescript: '>=5.4.0' peerDependenciesMeta: @@ -5930,8 +5930,8 @@ packages: typescript: optional: true - viem@2.57.1: - resolution: {integrity: sha512-eOV3fHnaMzkIFRefZg1icWztAKvBHg7RMKEH89ywY7hnyq1VxI4s/osXnTBViOsEZ7/LbbxU3w+JaIrbeIXRPQ==} + viem@2.55.10: + resolution: {integrity: sha512-Q9Ba+/ma81U2M5o5P2AQ7Ux8rTIwmCZvUcr8rKdQ22bV0IBFHllM2m5gWDP8hFaUN2nH2oW3QG44amRazflYNQ==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -8782,23 +8782,23 @@ snapshots: dependencies: vue: 3.5.40(typescript@6.0.3) - '@wagmi/connectors@8.0.13(@wagmi/core@3.4.11)(accounts@0.15.2)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3))': + '@wagmi/connectors@8.0.13(@wagmi/core@3.4.11)(accounts@0.15.2)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3))': dependencies: - '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) - viem: 2.57.1(typescript@6.0.3)(zod@4.4.3) + '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) + viem: 2.55.10(typescript@6.0.3)(zod@4.4.3) optionalDependencies: - accounts: 0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14) + accounts: 0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14) typescript: 6.0.3 - '@wagmi/core@3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3))': + '@wagmi/core@3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3))': dependencies: eventemitter3: 5.0.1 mipd: 0.0.7(typescript@6.0.3) - viem: 2.57.1(typescript@6.0.3)(zod@4.4.3) + viem: 2.55.10(typescript@6.0.3)(zod@4.4.3) zustand: 5.0.0(@types/react@19.2.14)(react@19.2.5)(use-sync-external-store@1.4.0(react@19.2.5)) optionalDependencies: '@tanstack/query-core': 5.100.10 - accounts: 0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14) + accounts: 0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14) typescript: 6.0.3 transitivePeerDependencies: - '@types/react' @@ -8834,16 +8834,16 @@ snapshots: jose: 6.2.3 mipd: 0.0.7(typescript@6.0.3) mppx: 0.8.9(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(express@5.2.1)(hono@4.13.7)(typescript@6.0.3)(viem@2.54.6(typescript@6.0.3)(zod@4.4.3)) - ox: 0.14.45(typescript@6.0.3)(zod@4.4.3) + ox: 0.14.33(typescript@6.0.3)(zod@4.4.3) wata: 0.4.0(react@19.2.5)(typescript@6.0.3) webauthx: 0.1.2(typescript@6.0.3)(zod@4.4.3) zod: 4.4.3 zustand: 5.0.13(@types/react@19.2.14)(react@19.2.5)(use-sync-external-store@1.4.0(react@19.2.5)) optionalDependencies: - '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) + '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) react: 19.2.5 viem: 2.54.6(typescript@6.0.3)(zod@4.4.3) - wagmi: 3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) + wagmi: 3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) transitivePeerDependencies: - '@modelcontextprotocol/sdk' - '@types/react' @@ -8854,23 +8854,23 @@ snapshots: - typescript - use-sync-external-store - accounts@0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14): + accounts@0.15.2(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@types/react@19.2.14)(@wagmi/core@3.4.11)(express@5.2.1)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3))(wagmi@3.6.14): dependencies: hono: 4.13.7 idb-keyval: 6.2.2 jose: 6.2.3 mipd: 0.0.7(typescript@6.0.3) - mppx: 0.8.9(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(express@5.2.1)(hono@4.13.7)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) - ox: 0.14.45(typescript@6.0.3)(zod@4.4.3) + mppx: 0.8.9(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(express@5.2.1)(hono@4.13.7)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) + ox: 0.14.33(typescript@6.0.3)(zod@4.4.3) wata: 0.4.0(react@19.2.5)(typescript@6.0.3) webauthx: 0.1.2(typescript@6.0.3)(zod@4.4.3) zod: 4.4.3 zustand: 5.0.13(@types/react@19.2.14)(react@19.2.5)(use-sync-external-store@1.4.0(react@19.2.5)) optionalDependencies: - '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) + '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) react: 19.2.5 - viem: 2.57.1(typescript@6.0.3)(zod@4.4.3) - wagmi: 3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) + viem: 2.55.10(typescript@6.0.3)(zod@4.4.3) + wagmi: 3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) transitivePeerDependencies: - '@modelcontextprotocol/sdk' - '@types/react' @@ -10902,13 +10902,13 @@ snapshots: transitivePeerDependencies: - typescript - mppx@0.8.9(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(express@5.2.1)(hono@4.13.7)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)): + mppx@0.8.9(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(express@5.2.1)(hono@4.13.7)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)): dependencies: '@stripe/stripe-js': 9.9.0 eventsource-parser: 3.1.0 incur: 0.4.19 ox: 0.14.30(typescript@6.0.3)(zod@4.4.3) - viem: 2.57.1(typescript@6.0.3)(zod@4.4.3) + viem: 2.55.10(typescript@6.0.3)(zod@4.4.3) zod: 4.4.3 optionalDependencies: '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3) @@ -11034,7 +11034,7 @@ snapshots: '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.3.0(typescript@6.0.3)(zod@4.4.3) + abitype: 1.2.3(typescript@6.0.3)(zod@4.4.3) eventemitter3: 5.0.1 optionalDependencies: typescript: 6.0.3 @@ -11056,7 +11056,7 @@ snapshots: transitivePeerDependencies: - zod - ox@0.14.45(typescript@6.0.3)(zod@4.4.3): + ox@0.14.33(typescript@6.0.3)(zod@4.4.3): dependencies: '@adraffy/ens-normalize': 1.11.1 '@noble/ciphers': 1.3.0 @@ -11064,7 +11064,7 @@ snapshots: '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.3.0(typescript@6.0.3)(zod@4.4.3) + abitype: 1.2.3(typescript@6.0.3)(zod@4.4.3) eventemitter3: 5.0.1 optionalDependencies: typescript: 6.0.3 @@ -12187,7 +12187,7 @@ snapshots: abitype: 1.3.0(typescript@6.0.3)(zod@4.4.3) kysely: 0.28.17 mitt: 3.0.1 - ox: 0.14.20(typescript@6.0.3)(zod@4.4.3) + ox: 0.14.30(typescript@6.0.3)(zod@4.4.3) zod: 4.4.3 transitivePeerDependencies: - typescript @@ -12515,7 +12515,7 @@ snapshots: - utf-8-validate - zod - viem@2.57.1(typescript@6.0.3)(zod@4.4.3): + viem@2.55.10(typescript@6.0.3)(zod@4.4.3): dependencies: '@noble/curves': 1.9.1 '@noble/hashes': 1.8.0 @@ -12523,7 +12523,7 @@ snapshots: '@scure/bip39': 1.6.0 abitype: 1.2.3(typescript@6.0.3)(zod@4.4.3) isows: 1.0.7(ws@8.21.0) - ox: 0.14.45(typescript@6.0.3)(zod@4.4.3) + ox: 0.14.33(typescript@6.0.3)(zod@4.4.3) ws: 8.21.0 optionalDependencies: typescript: 6.0.3 @@ -12736,14 +12736,14 @@ snapshots: w3c-keyname@2.2.8: {} - wagmi@3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)): + wagmi@3.6.14(@tanstack/query-core@5.100.10)(@tanstack/react-query@5.100.10(react@19.2.5))(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)): dependencies: '@tanstack/react-query': 5.100.10(react@19.2.5) - '@wagmi/connectors': 8.0.13(@wagmi/core@3.4.11)(accounts@0.15.2)(typescript@6.0.3)(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) - '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.57.1(typescript@6.0.3)(zod@4.4.3)) + '@wagmi/connectors': 8.0.13(@wagmi/core@3.4.11)(accounts@0.15.2)(typescript@6.0.3)(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) + '@wagmi/core': 3.4.11(@tanstack/query-core@5.100.10)(@types/react@19.2.14)(accounts@0.15.2)(react@19.2.5)(typescript@6.0.3)(use-sync-external-store@1.4.0(react@19.2.5))(viem@2.55.10(typescript@6.0.3)(zod@4.4.3)) react: 19.2.5 use-sync-external-store: 1.4.0(react@19.2.5) - viem: 2.57.1(typescript@6.0.3)(zod@4.4.3) + viem: 2.55.10(typescript@6.0.3)(zod@4.4.3) optionalDependencies: typescript: 6.0.3 transitivePeerDependencies: @@ -12954,6 +12954,7 @@ time: chat@4.27.0: '2026-04-30T20:46:13.887Z' emulate@0.5.0: '2026-04-29T05:49:35.977Z' kysely@0.28.17: '2026-05-03T01:05:34.179Z' + ox@0.14.20: '2026-04-21T20:34:36.837Z' react-dom@19.2.5: '2026-04-08T18:39:31.423Z' react@19.2.5: '2026-04-08T18:39:24.455Z' tailwindcss@4.2.4: '2026-04-21T13:15:55.494Z' diff --git a/src/chat.workers.test.ts b/src/chat.workers.test.ts index 60431a4..c390ac2 100644 --- a/src/chat.workers.test.ts +++ b/src/chat.workers.test.ts @@ -7362,7 +7362,7 @@ describe('/tip config', () => { }, { timeout: 10_000 }, // 10 seconds ) - .toEqual(['pathUSD', 'USDC.e', 'USDT0']) + .toEqual(['OUSD', 'pathUSD', 'USDC.e', 'USDT0']) fetchSpy.mockRestore() }, 20_000) // 20 seconds diff --git a/src/lib/tempo.test.ts b/src/lib/tempo.test.ts index a92aa2c..ef85f7a 100644 --- a/src/lib/tempo.test.ts +++ b/src/lib/tempo.test.ts @@ -28,7 +28,7 @@ test('returns optional RPC URLs by chain', () => { test('returns default token by chain', () => { expect(Tempo.addressLookup.ousd).toBe('0x20c0000000000000000000006a37DA5C996874BE') expect(Tempo.getDefaultTokenAddress(Tempo.chainLookup.mainnet)).toBe(Tempo.addressLookup.ousd) - expect(Tempo.getDefaultTokenAddress(Tempo.chainLookup.testnet)).toBe(Tempo.addressLookup.pathUsd) + expect(Tempo.getDefaultTokenAddress(Tempo.chainLookup.testnet)).toBe(Tempo.addressLookup.ousd) expect(Tempo.getDefaultTokenAddress(Tempo.chainLookup.localnet)).toBe(Tempo.addressLookup.pathUsd) }) @@ -38,7 +38,8 @@ test('checks allowed tokens by chain', () => { expect(Tempo.isAllowedToken(Tempo.chainLookup.mainnet, Tempo.addressLookup.usdcE)).toBe(true) expect(Tempo.isAllowedToken(Tempo.chainLookup.mainnet, Tempo.addressLookup.usdt0)).toBe(true) expect(Tempo.isAllowedToken(Tempo.chainLookup.mainnet, Tempo.addressLookup.alphaUsd)).toBe(false) - expect(Tempo.isAllowedToken(Tempo.chainLookup.testnet, Tempo.addressLookup.ousd)).toBe(false) + expect(Tempo.isAllowedToken(Tempo.chainLookup.testnet, Tempo.addressLookup.ousd)).toBe(true) + expect(Tempo.isAllowedToken(Tempo.chainLookup.localnet, Tempo.addressLookup.ousd)).toBe(false) expect(Tempo.isAllowedToken(Tempo.chainLookup.testnet, Tempo.addressLookup.pathUsd)).toBe(true) expect(Tempo.isAllowedToken(Tempo.chainLookup.testnet, Tempo.addressLookup.alphaUsd)).toBe(true) expect(Tempo.isAllowedToken(Tempo.chainLookup.testnet, Tempo.addressLookup.betaUsd)).toBe(true) @@ -50,7 +51,8 @@ test('checks allowed tokens by chain', () => { test('resolves supported token aliases', () => { expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'OUSD')).toBe(Tempo.addressLookup.ousd) expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'OpenUSD')).toBe(Tempo.addressLookup.ousd) - expect(Tempo.getTokenAddress(Tempo.chainLookup.testnet, 'ousd')).toBe(null) + expect(Tempo.getTokenAddress(Tempo.chainLookup.testnet, 'ousd')).toBe(Tempo.addressLookup.ousd) + expect(Tempo.getTokenAddress(Tempo.chainLookup.localnet, 'ousd')).toBe(null) expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'USDC.e')).toBe(Tempo.addressLookup.usdcE) expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'usdc')).toBe(Tempo.addressLookup.usdcE) expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'USDT')).toBe(Tempo.addressLookup.usdt0) diff --git a/src/lib/tempo.ts b/src/lib/tempo.ts index 8e5bd53..2414be9 100644 --- a/src/lib/tempo.ts +++ b/src/lib/tempo.ts @@ -1,11 +1,10 @@ import { Address } from 'ox' import { tempo, tempoLocalnet, tempoModerato } from 'viem/tempo/chains' -import { ousd } from 'viem/tokens' export const addressLookup = { alphaUsd: Address.checksum('0x20c0000000000000000000000000000000000001'), betaUsd: Address.checksum('0x20c0000000000000000000000000000000000002'), - ousd: Address.checksum(ousd.addresses[tempo.id]), + ousd: Address.checksum('0x20c0000000000000000000006a37DA5C996874BE'), pathUsd: Address.checksum('0x20c0000000000000000000000000000000000000'), thetaUsd: Address.checksum('0x20c0000000000000000000000000000000000003'), usdcE: Address.checksum('0x20C000000000000000000000b9537d11c60E8b50'), @@ -26,7 +25,7 @@ export function getChain(chainId: number) { } export function getDefaultTokenAddress(chainId: number) { - if (chainId === chainLookup.mainnet) return addressLookup.ousd + if (chainId === chainLookup.mainnet || chainId === chainLookup.testnet) return addressLookup.ousd return addressLookup.pathUsd } @@ -76,7 +75,15 @@ export function isAllowedToken(chainId: number, tokenAddress: string) { addressLookup.usdcE, addressLookup.usdt0, ].some((allowed) => Address.isEqual(token, allowed)) - if (chainId === chainLookup.testnet || chainId === chainLookup.localnet) + if (chainId === chainLookup.testnet) + return [ + addressLookup.ousd, + addressLookup.pathUsd, + addressLookup.alphaUsd, + addressLookup.betaUsd, + addressLookup.thetaUsd, + ].some((allowed) => Address.isEqual(token, allowed)) + if (chainId === chainLookup.localnet) return [ addressLookup.pathUsd, addressLookup.alphaUsd, From 695906a1abbd92fdf1781a700bffdb893011d985 Mon Sep 17 00:00:00 2001 From: Derek <256792747+decofe@users.noreply.github.com> Date: Wed, 30 Sep 2026 13:27:26 +0000 Subject: [PATCH 3/5] test: use chain default token in account link tests Co-authored-by: Derek Cofausper <256792747+decofe@users.noreply.github.com> --- src/api.workers.test.ts | 11 +++++++---- src/chat.workers.test.ts | 12 +++++++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/api.workers.test.ts b/src/api.workers.test.ts index d27eb74..714d513 100644 --- a/src/api.workers.test.ts +++ b/src/api.workers.test.ts @@ -1509,7 +1509,7 @@ describe('/api/account/link/:token', () => { accessKeyAddress: pending.accessKey.address, accessKeyPublicKey: pending.accessKey.publicKey, ok: true, - tokenAddress: Tempo.addressLookup.pathUsd, + tokenAddress: Tempo.getDefaultTokenAddress(pending.workspace.chain_id), }) }) @@ -1906,7 +1906,8 @@ describe('/api/confirm/:token', () => { recipientProviderUserId: 'twitter-confirm-recipient', senderProviderUserId: 'twitter-confirm-sender', source: 'mention', - tokenAddress: workspace.default_token_address ?? Tempo.addressLookup.pathUsd, + tokenAddress: + workspace.default_token_address ?? Tempo.getDefaultTokenAddress(workspace.chain_id), workspaceId: workspace.id, }) @@ -1973,7 +1974,8 @@ describe('/api/confirm/:token', () => { recipientProviderUserId, senderProviderUserId, source: 'mention', - tokenAddress: workspace.default_token_address ?? Tempo.addressLookup.pathUsd, + tokenAddress: + workspace.default_token_address ?? Tempo.getDefaultTokenAddress(workspace.chain_id), workspaceId: workspace.id, } satisfies Confirmation.Payload const token = await Confirmation.encrypt(env, payload) @@ -3106,7 +3108,8 @@ async function signKeyAuthorization( chainId: pending.workspace.chain_id, expiresAt: pending.link.access_key_expires_at, tokenAddress: Address.checksum( - pending.workspace.default_token_address ?? Tempo.addressLookup.pathUsd, + pending.workspace.default_token_address ?? + Tempo.getDefaultTokenAddress(pending.workspace.chain_id), ), }) } diff --git a/src/chat.workers.test.ts b/src/chat.workers.test.ts index c390ac2..2dfd7d8 100644 --- a/src/chat.workers.test.ts +++ b/src/chat.workers.test.ts @@ -3463,7 +3463,9 @@ test('@Tipbot mention connect link completion connects local workspace account', accessKeyAddress: link.access_key_address, chainId: link.chain_id, expiresAt: link.access_key_expires_at, - tokenAddress: Address.checksum(link.default_token_address ?? Tempo.addressLookup.pathUsd), + tokenAddress: Address.checksum( + link.default_token_address ?? Tempo.getDefaultTokenAddress(link.chain_id), + ), }) const completeResponse = await client.api.account.link[':token'].$post({ @@ -3716,7 +3718,9 @@ test('@Tipbot mention connect link completion notifies Slack Connect external ac accessKeyAddress: link.access_key_address, chainId: link.chain_id, expiresAt: link.access_key_expires_at, - tokenAddress: Address.checksum(link.default_token_address ?? Tempo.addressLookup.pathUsd), + tokenAddress: Address.checksum( + link.default_token_address ?? Tempo.getDefaultTokenAddress(link.chain_id), + ), }) const completeResponse = await client.api.account.link[':token'].$post({ @@ -4527,7 +4531,9 @@ test('@Tipbot mention claims Slack Connect pending tip when recipient connects', accessKeyAddress: link.access_key_address, chainId: link.chain_id, expiresAt: link.access_key_expires_at, - tokenAddress: Address.checksum(link.default_token_address ?? Tempo.addressLookup.pathUsd), + tokenAddress: Address.checksum( + link.default_token_address ?? Tempo.getDefaultTokenAddress(link.chain_id), + ), }), }, param: { token }, From 36ebb6dea8dc9e78c42a3167907dcc8fb9167381 Mon Sep 17 00:00:00 2001 From: Brendan Ryan <1572504+brendanjryan@users.noreply.github.com> Date: Wed, 4 Nov 2026 14:15:21 -0800 Subject: [PATCH 4/5] fix: resolve generic usd alias to the chain default token --- src/lib/tempo.test.ts | 6 ++++++ src/lib/tempo.ts | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/lib/tempo.test.ts b/src/lib/tempo.test.ts index ef85f7a..88734ff 100644 --- a/src/lib/tempo.test.ts +++ b/src/lib/tempo.test.ts @@ -53,6 +53,12 @@ test('resolves supported token aliases', () => { expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'OpenUSD')).toBe(Tempo.addressLookup.ousd) expect(Tempo.getTokenAddress(Tempo.chainLookup.testnet, 'ousd')).toBe(Tempo.addressLookup.ousd) expect(Tempo.getTokenAddress(Tempo.chainLookup.localnet, 'ousd')).toBe(null) + expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'usd')).toBe(Tempo.addressLookup.ousd) + expect(Tempo.getTokenAddress(Tempo.chainLookup.testnet, 'usd')).toBe(Tempo.addressLookup.ousd) + expect(Tempo.getTokenAddress(Tempo.chainLookup.localnet, 'usd')).toBe(Tempo.addressLookup.pathUsd) + expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'pathUSD')).toBe( + Tempo.addressLookup.pathUsd, + ) expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'USDC.e')).toBe(Tempo.addressLookup.usdcE) expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'usdc')).toBe(Tempo.addressLookup.usdcE) expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'USDT')).toBe(Tempo.addressLookup.usdt0) diff --git a/src/lib/tempo.ts b/src/lib/tempo.ts index 2414be9..3ac9e9a 100644 --- a/src/lib/tempo.ts +++ b/src/lib/tempo.ts @@ -100,8 +100,8 @@ export function getTokenAddress(chainId: number, value: string) { const normalized = value.toLowerCase().replace(/[.\-_\s]/g, '') const tokenAddress = (() => { if (normalized === 'ousd' || normalized === 'openusd') return addressLookup.ousd - if (normalized === 'pathusd' || normalized === 'path' || normalized === 'usd') - return addressLookup.pathUsd + if (normalized === 'pathusd' || normalized === 'path') return addressLookup.pathUsd + if (normalized === 'usd') return getDefaultTokenAddress(chainId) if (normalized === 'usdce' || normalized === 'usdc') return addressLookup.usdcE if (normalized === 'usdt0' || normalized === 'usdt') return addressLookup.usdt0 if (normalized === 'alphausd' || normalized === 'alpha') return addressLookup.alphaUsd From 13ce444f2643e00c852b4f2d37c2db1b164c6b56 Mon Sep 17 00:00:00 2001 From: Brendan Ryan <1572504+brendanjryan@users.noreply.github.com> Date: Wed, 4 Nov 2026 14:19:44 -0800 Subject: [PATCH 5/5] fix: resolve usd to the workspace default and set Tempo workspace to OUSD --- db/migrations/0026_tempo_workspace_ousd.sql | 8 ++++++++ src/chat.ts | 6 +++++- src/lib/tempo.test.ts | 6 ++++++ src/lib/tempo.ts | 11 +++++++++-- src/lib/twitter.ts | 6 +++++- 5 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 db/migrations/0026_tempo_workspace_ousd.sql diff --git a/db/migrations/0026_tempo_workspace_ousd.sql b/db/migrations/0026_tempo_workspace_ousd.sql new file mode 100644 index 0000000..b9ea308 --- /dev/null +++ b/db/migrations/0026_tempo_workspace_ousd.sql @@ -0,0 +1,8 @@ +-- Make OUSD the default tip token for Tempo's own Slack workspace (T098H03GGE6) on mainnet. +UPDATE "workspace" +SET + "default_token_address" = '0x20c0000000000000000000006a37DA5C996874BE', + "updated_at" = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') +WHERE "provider" = 'slack' + AND "provider_id" = 'T098H03GGE6' + AND "chain_id" = 4217; diff --git a/src/chat.ts b/src/chat.ts index 580279d..4af4996 100644 --- a/src/chat.ts +++ b/src/chat.ts @@ -2248,7 +2248,11 @@ const handlers = { } const tokenAddress = parsed.token - ? Tempo.getTokenAddress(workspace?.chain_id ?? Tempo.chainLookup.mainnet, parsed.token) + ? Tempo.getTokenAddress( + workspace?.chain_id ?? Tempo.chainLookup.mainnet, + parsed.token, + workspace?.default_token_address, + ) : null if (parsed.token && !tokenAddress) { await postPrivateReply( diff --git a/src/lib/tempo.test.ts b/src/lib/tempo.test.ts index 88734ff..75a5e0c 100644 --- a/src/lib/tempo.test.ts +++ b/src/lib/tempo.test.ts @@ -56,6 +56,12 @@ test('resolves supported token aliases', () => { expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'usd')).toBe(Tempo.addressLookup.ousd) expect(Tempo.getTokenAddress(Tempo.chainLookup.testnet, 'usd')).toBe(Tempo.addressLookup.ousd) expect(Tempo.getTokenAddress(Tempo.chainLookup.localnet, 'usd')).toBe(Tempo.addressLookup.pathUsd) + expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'usd', Tempo.addressLookup.pathUsd)).toBe( + Tempo.addressLookup.pathUsd, + ) + expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'usd', Tempo.addressLookup.usdcE)).toBe( + Tempo.addressLookup.usdcE, + ) expect(Tempo.getTokenAddress(Tempo.chainLookup.mainnet, 'pathUSD')).toBe( Tempo.addressLookup.pathUsd, ) diff --git a/src/lib/tempo.ts b/src/lib/tempo.ts index 3ac9e9a..4d99ef4 100644 --- a/src/lib/tempo.ts +++ b/src/lib/tempo.ts @@ -93,7 +93,11 @@ export function isAllowedToken(chainId: number, tokenAddress: string) { return false } -export function getTokenAddress(chainId: number, value: string) { +export function getTokenAddress( + chainId: number, + value: string, + defaultTokenAddress?: string | null, +) { const address = Address.validate(value) ? Address.checksum(value) : null if (address && isAllowedToken(chainId, address)) return address @@ -101,7 +105,10 @@ export function getTokenAddress(chainId: number, value: string) { const tokenAddress = (() => { if (normalized === 'ousd' || normalized === 'openusd') return addressLookup.ousd if (normalized === 'pathusd' || normalized === 'path') return addressLookup.pathUsd - if (normalized === 'usd') return getDefaultTokenAddress(chainId) + if (normalized === 'usd') + return defaultTokenAddress + ? Address.checksum(defaultTokenAddress) + : getDefaultTokenAddress(chainId) if (normalized === 'usdce' || normalized === 'usdc') return addressLookup.usdcE if (normalized === 'usdt0' || normalized === 'usdt') return addressLookup.usdt0 if (normalized === 'alphausd' || normalized === 'alpha') return addressLookup.alphaUsd diff --git a/src/lib/twitter.ts b/src/lib/twitter.ts index e6bb395..5b92028 100644 --- a/src/lib/twitter.ts +++ b/src/lib/twitter.ts @@ -1086,7 +1086,11 @@ export async function parseTwitterTip(env: Env, input: TwitterTweetInput) { let tokenAddress = null if (parsed.token) { const workspace = await ensureTwitterWorkspace(DB.create(env.DB), new Date().toISOString()) - tokenAddress = Tempo.getTokenAddress(workspace.chain_id, parsed.token) + tokenAddress = Tempo.getTokenAddress( + workspace.chain_id, + parsed.token, + workspace.default_token_address, + ) if (!tokenAddress) return null } if (Tip.isTransferMemoTooLong(parsed.memo)) return null