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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@
"@tanstack/router-plugin": "1.167.35",
"accounts": "^0.14.1",
"chat": "4.27.0",
"hono": "4.12.25",
"hono": "4.12.27",
"kysely": "0.28.17",
"nanoid": "^5.1.11",
"ox": "0.14.20",
"react": "19.2.5",
"react-dom": "19.2.5",
"tapimo": "0.5.2",
"viem": "^2.50.4",
"viem": "^2.55.10",
"wagmi": "^3.6.14",
"zod": "4.4.3"
},
Expand Down
548 changes: 308 additions & 240 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

16 changes: 11 additions & 5 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,13 @@ minimumReleaseAgeExclude:
- esbuild@0.28.1
- protobufjs@7.6.5
- form-data@4.0.6
- tar@7.5.20
- vite-plus@0.1.24
- launch-editor@2.14.1
- hono@4.12.25
- hono@4.12.27
- fast-uri@3.1.4
- sharp@0.35.0
- brace-expansion@5.0.8
- tar@7.5.21
- undici@7.28.0
- js-yaml@4.3.0
- ws@8.21.0
Expand All @@ -56,15 +59,18 @@ overrides:
'@babel/core': 7.29.6
'@grpc/grpc-js': 1.14.4
axios: 1.18.0
brace-expansion: 2.1.2
'@hono/node-server@<2.0.5': 2.0.10
brace-expansion: 5.0.8
esbuild: 0.28.1
form-data: 4.0.6
hono: 4.12.25
fast-uri: 3.1.4
hono: 4.12.27
js-yaml: 4.3.0
launch-editor: 2.14.1
protobufjs: 7.6.5
shell-quote: 1.10.0
tar: 7.5.20
sharp: 0.35.0
tar: 7.5.21
tmp: 0.2.7
undici: 7.28.0
uuid: 11.1.1
Expand Down
4 changes: 2 additions & 2 deletions src/api.workers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1890,7 +1890,7 @@ describe('/api/confirm/:token', () => {
const workspace = await ensureTwitterTestWorkspace()
mockTwitterUser({ id: 'twitter-confirm-recipient', username: 'alice' })
const token = await Confirmation.encrypt(env, {
accessKeyExpiresAt: new Date(Date.now() + AccountLink.reusableAccessKeyTtlMs).toISOString(), // 30 days
accessKeyExpiresAt: new Date(Date.now() + AccountLink.reusableAccessKeyTtlMs).toISOString(), // 90 days
amount: 5_000_000,
chainId: workspace.chain_id,
expiresAt: new Date(Date.now() + AccountLink.confirmationLinkTtlMs).toISOString(), // 10 minutes
Expand Down Expand Up @@ -2611,7 +2611,7 @@ async function createConfirmationToken(
? {
accessKeyExpiresAt: new Date(
Date.now() + AccountLink.reusableAccessKeyTtlMs,
).toISOString(), // 30 days
).toISOString(), // 90 days
}
: {}),
amount,
Expand Down
8 changes: 5 additions & 3 deletions src/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,7 @@ const modalSubmits = {
}),
{ account: creator.address as Address.Address, token: tokenAddress as Address.Address },
)
if (BigInt(amount) > balance) {
if (BigInt(amount) > balance.amount) {
await postConnectLink(
{
channel: getChat().channel(`slack:${metadata.channelId}`),
Expand Down Expand Up @@ -1722,7 +1722,7 @@ const handlers = {
account: member.account_address as Address.Address,
token: token.address as Address.Address,
})
return { balance, label: token.label }
return { balance: balance.amount, label: token.label }
} catch {
return { balance: 0n, label: token.label }
}
Expand Down Expand Up @@ -6072,7 +6072,9 @@ async function postConnectLink(event: TipEvent, ctx: HandlerContext) {
const linkUrl = `https://${env.HOST}/connect/${token}`
const linkText = `${accountId ? 'Refresh Tipbot connection' : 'Connect to Tipbot'}: ${linkUrl}\n${linkDescription}`
const linkExpiresAt = new Date(now.getTime() + 10 * 60 * 1000).toISOString() // 10 minutes
const accessKeyExpiresAt = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000).toISOString() // 30 days
const accessKeyExpiresAt = new Date(
now.getTime() + AccountLink.reusableAccessKeyTtlMs,
).toISOString()
await ctx.db
.deleteFrom('account_link_token')
.where('member_id', '=', member.id)
Expand Down
2 changes: 1 addition & 1 deletion src/lib/accountLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as Tempo from '#/lib/tempo.ts'
export const reusableAccessKeyLimit = 10_000_000
export const reusableAccessKeyLimitText = '10'
export const reusableAccessKeyPeriodSeconds = 24 * 60 * 60 // 1 day
export const reusableAccessKeyTtlMs = 30 * 24 * 60 * 60 * 1000 // 30 days
export const reusableAccessKeyTtlMs = 90 * 24 * 60 * 60 * 1000 // 90 days
export const confirmationLinkTtlMs = 10 * 60 * 1000 // 10 minutes

export async function hashToken(env: Pick<Env, 'SECRET_KEY'>, token: string) {
Expand Down
8 changes: 4 additions & 4 deletions src/lib/tip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ export async function checkReusableTipAccessKey(
account: sender.account.address as Address.Address,
token: tokenAddress as Address.Address,
})
if (balance < BigInt(input.amount)) return { code: 'insufficient_funds', ok: false }
if (balance.amount < BigInt(input.amount)) return { code: 'insufficient_funds', ok: false }
return { memberId: sender.member.id, ok: true }
}

Expand Down Expand Up @@ -1990,7 +1990,7 @@ async function submitTipBatch(
account: input.sender.account.address as Address.Address,
token: input.tokenAddress as Address.Address,
})
if (balance < BigInt(totalAmount)) throw new InsufficientFundsError()
if (balance.amount < BigInt(totalAmount)) throw new InsufficientFundsError()

const calls = input.connectedRecipients.map((recipient) =>
Actions.token.transfer.call({
Expand Down Expand Up @@ -2308,7 +2308,7 @@ async function submitSignedTipBatch(
account: input.sender.account.address as Address.Address,
token: input.tokenAddress as Address.Address,
})
if (balance < BigInt(input.payload.amount * input.connectedRecipients.length))
if (balance.amount < BigInt(input.payload.amount * input.connectedRecipients.length))
throw new InsufficientFundsError()

const receipt = (await client.request({
Expand Down Expand Up @@ -2479,7 +2479,7 @@ async function submitSignedTip(
account: input.sender.account.address as Address.Address,
token: input.tokenAddress as Address.Address,
})
if (balance < BigInt(input.payload.amount)) throw new InsufficientFundsError()
if (balance.amount < BigInt(input.payload.amount)) throw new InsufficientFundsError()

const receipt = (await client.request({
method: 'eth_sendRawTransactionSync' as never,
Expand Down
28 changes: 20 additions & 8 deletions test/e2e/connect.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { APIRequestContext } from '@playwright/test'
import type { APIRequestContext, APIResponse } from '@playwright/test'
import type { Kysely } from 'kysely'
import { WebClient } from '@slack/web-api'
import * as AccessKey from '#/lib/accessKey.ts'
Expand Down Expand Up @@ -284,13 +284,25 @@ async function installSlack(
if (!callbackLocation) throw new Error('Expected Slack OAuth callback redirect location.')

const callbackUrl = new URL(callbackLocation)
const callbackResponse = await request.get(
app.url(`${callbackUrl.pathname}${callbackUrl.search}` as `/api/${string}`),
{
maxRedirects: 0,
},
)
expect(callbackResponse.status(), await callbackResponse.text()).toBe(302)
let callbackResponse: APIResponse | undefined
let callbackResponseText = ''
for (let attempt = 0; attempt < 3; attempt += 1) {
callbackResponse = await request.get(
app.url(`${callbackUrl.pathname}${callbackUrl.search}` as `/api/${string}`),
{
maxRedirects: 0,
},
)
callbackResponseText = await callbackResponse.text()
if (callbackResponse.status() === 302) break
if (
!callbackResponseText.includes('D1_ERROR') ||
!callbackResponseText.includes('internal error')
)
break
await new Promise((resolve) => setTimeout(resolve, 100)) // 100 milliseconds
}
expect(callbackResponse?.status(), callbackResponseText).toBe(302)
}

async function postSlashCommand(app: { url: (path: `/api/${string}`) => string }, text: string) {
Expand Down
Loading