diff --git a/packages/cli/src/commands/spend-request/__tests__/spend-request.test.tsx b/packages/cli/src/commands/spend-request/__tests__/spend-request.test.tsx index 52cd153..fffd85a 100644 --- a/packages/cli/src/commands/spend-request/__tests__/spend-request.test.tsx +++ b/packages/cli/src/commands/spend-request/__tests__/spend-request.test.tsx @@ -234,6 +234,93 @@ describe('spend-request', () => { }); }); + describe('activity_url', () => { + it('RetrieveSpendRequest shows activity_url in finalized phase', async () => { + const request = makeSpendRequest({ + status: 'succeeded', + activity_url: 'https://activity.link.com/tx_123', + }); + const repo = makeMockRepo(request); + + const { lastFrame } = render( + {}} + />, + ); + + await vi.waitFor(() => { + const frame = lastFrame(); + expect(frame).toContain('Activity URL'); + expect(frame).toContain('https://activity.link.com/tx_123'); + }); + }); + + it('RetrieveSpendRequest shows link_transaction_id in finalized phase', async () => { + const request = makeSpendRequest({ + status: 'succeeded', + link_transaction_id: 'ltxn_abc123', + }); + const repo = makeMockRepo(request); + + const { lastFrame } = render( + {}} + />, + ); + + await vi.waitFor(() => { + const frame = lastFrame(); + expect(frame).toContain('Transaction ID'); + expect(frame).toContain('ltxn_abc123'); + }); + }); + + it('RetrieveSpendRequest omits activity_url on failed status even when present', async () => { + const request = makeSpendRequest({ + status: 'failed', + activity_url: 'https://activity.link.com/tx_123', + }); + const repo = makeMockRepo(request); + + const { lastFrame } = render( + {}} + />, + ); + + await vi.waitFor(() => { + const frame = lastFrame(); + expect(frame).toContain('terminal status'); + expect(frame).not.toContain('Activity URL'); + }); + }); + + it('RetrieveSpendRequest omits activity_url when absent in finalized phase', async () => { + const request = makeSpendRequest({ status: 'succeeded' }); + const repo = makeMockRepo(request); + + const { lastFrame } = render( + {}} + />, + ); + + await vi.waitFor(() => { + const frame = lastFrame(); + expect(frame).toContain('terminal status'); + expect(frame).not.toContain('Activity URL'); + }); + }); + }); + describe('sanitization', () => { it('CreateSpendRequest sanitizes merchant_name and line_items', async () => { const request = makeSpendRequest(); diff --git a/packages/cli/src/commands/spend-request/retrieve.tsx b/packages/cli/src/commands/spend-request/retrieve.tsx index 0716923..32ad208 100644 --- a/packages/cli/src/commands/spend-request/retrieve.tsx +++ b/packages/cli/src/commands/spend-request/retrieve.tsx @@ -287,6 +287,23 @@ export const RetrieveSpendRequest: React.FC = ({ )} )} + {request?.link_transaction_id && ( + + + Transaction ID: {request.link_transaction_id} + + + )} + {request?.status === 'succeeded' && request?.activity_url && ( + + + Activity URL:{' '} + + {request.activity_url} + + + + )} ); diff --git a/packages/sdk/src/types/index.ts b/packages/sdk/src/types/index.ts index cceee7b..a9c9c68 100644 --- a/packages/sdk/src/types/index.ts +++ b/packages/sdk/src/types/index.ts @@ -132,6 +132,8 @@ export interface SpendRequest { shared_payment_token?: SharedPaymentToken; link_pay_token?: string; payment_status_details?: PaymentStatusDetails | null; + link_transaction_id?: string; + activity_url?: string; created_at: string; updated_at: string; }