Skip to content
Open
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
6 changes: 6 additions & 0 deletions .changeset/ord-1856.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@lifi/perps-types": minor
"@lifi/perps-sdk": minor
---

Add `SetupAgreement` and the optional `SetupAction.agreements` list, which names the documents a user must accept before a setup step executes.
33 changes: 31 additions & 2 deletions packages/perps-sdk/src/services/getProviders.unit.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import type { ProvidersResponse, SetupAgreement } from '@lifi/perps-types'
import { HttpResponse, http } from 'msw'
import { describe, expect, it } from 'vitest'
import { mockProviders } from '../../test/handlers.js'
import { createPerpsClient } from '../client/createPerpsClient.js'
import { mockProviders, server } from '../../test/handlers.js'
import {
createPerpsClient,
DEFAULT_API_URL,
} from '../client/createPerpsClient.js'
import { getProviders } from './getProviders.js'

describe('getProviders', () => {
Expand Down Expand Up @@ -32,6 +37,30 @@ describe('getProviders', () => {
])
})

it('passes setup agreements through unchanged', async () => {
const agreements: SetupAgreement[] = [
{ title: 'Terms of Use', url: 'https://example.invalid/terms' },
{ title: 'Privacy Policy', url: 'https://example.invalid/privacy' },
]
const [provider] = mockProviders.providers
const fixture: ProvidersResponse = {
providers: [
{
...provider,
setup: [{ ...provider.setup[0], agreements }],
},
],
}
server.use(
http.get(`${DEFAULT_API_URL}/providers`, () => HttpResponse.json(fixture))
)

const result = await getProviders(client)

expect(result.providers[0].setup[0].agreements).toEqual(agreements)
expect(result).toEqual(fixture)
})

it('should support AbortSignal', async () => {
const controller = new AbortController()
controller.abort()
Expand Down
7 changes: 6 additions & 1 deletion packages/perps-types/src/index.unit.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { describe, expect, it } from 'vitest'
import { describe, expect, expectTypeOf, it } from 'vitest'
import * as perpsTypes from './index.js'
import type { SetupAgreement } from './providers.js'

describe('@lifi/perps-types runtime surface', () => {
it('exports no function; runtime helpers belong in @lifi/perps-sdk', () => {
Expand All @@ -9,4 +10,8 @@ describe('@lifi/perps-types runtime surface', () => {

expect(functions).toEqual([])
})

it('exports SetupAgreement', () => {
expectTypeOf<perpsTypes.SetupAgreement>().toEqualTypeOf<SetupAgreement>()
})
})
17 changes: 17 additions & 0 deletions packages/perps-types/src/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ export interface SetupOption<T extends ActionType = ActionType> {
default?: true
}

/**
* A document, such as terms of use or a privacy policy, that the user must
* accept before a setup step executes.
*
* @public
*/
export interface SetupAgreement {
title: string
url: string
}

/**
* One `Provider.setup` step. A choice step (`options !== null`) declares no
* `params`: each option carries its own bound params.
Expand All @@ -115,6 +126,12 @@ export interface SetupAction extends ProviderAction {
options: SetupOption[] | null
/** A `Provider.actions` entry that undoes the satisfied step, or `null`. */
revoke: ActionType | null
/**
* Documents the step asks the user to accept. A UI must show each entry as
* a link with its own checkbox, and must execute the step only after the
* user accepts all entries.
*/
agreements?: SetupAgreement[]
}

/**
Expand Down
11 changes: 11 additions & 0 deletions packages/perps-types/src/providers.unit.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type {
ProviderCategory,
ProviderFunding,
SetupAction,
SetupAgreement,
SetupOption,
TradeNotice,
} from './providers.js'
Expand Down Expand Up @@ -435,6 +436,13 @@ type _SetupOptionDescriptionShape = Expect<
type _SetupOptionDescriptionIsOptional = Expect<
Equals<Extract<RequiredKeys<SetupOption>, 'description'>, never>
>
type _SetupAgreementKeys = Expect<Equals<keyof SetupAgreement, 'title' | 'url'>>
type _SetupAgreementsShape = Expect<
Equals<SetupAction['agreements'], SetupAgreement[] | undefined>
>
type _SetupAgreementsIsOptional = Expect<
Equals<Extract<RequiredKeys<SetupAction>, 'agreements'>, never>
>
type _SignerIsSingle = Expect<Equals<ProviderAction['signer'], PerpsSigner>>
type _RelayShape = Expect<Equals<ProviderAction['relay'], ActionRelay>>
type _NoOptionsField = Expect<Equals<Extract<keyof Provider, 'options'>, never>>
Expand Down Expand Up @@ -613,6 +621,9 @@ export type _TypeAssertions = [
_SetupOptionBindsParams,
_SetupOptionDescriptionShape,
_SetupOptionDescriptionIsOptional,
_SetupAgreementKeys,
_SetupAgreementsShape,
_SetupAgreementsIsOptional,
_SignerIsSingle,
_RelayShape,
_NoOptionsField,
Expand Down
Loading